#
# hello.serial.i0.45.cad
#
# tiny45 serial I/O hello-world
#
# Neil Gershenfeld
# CBA MIT 11/15/07
#
# (c) Massachusetts Institute of Technology 2007
# Permission granted for experimental and personal use;
# license for commercial sale available from MIT.
#

#
# define shapes and transformation
#
# circle(x0, y0, r)
# cylinder(x0, y0, z0, z1, r)
# cone(x0, y0, z0, z1, r0)
# sphere(x0, y0, z0, r)
# torus(x0, y0, z0, r0, r1)
# rectangle(x0, x1, y0, y1)
# cube(x0, x1, y0, y1, z0, z1)
# triangle(x0, y0, x1, y1, x2, y2) (points in clockwise order)
# pyramid(x0, x1, y0, y1, z0, z1)
# function(Z_of_XY)
# functions(upper_Z_of_XY,lower_Z_of_XY)
# add(part1, part2)
# subtract(part1, part2)
# intersect(part1, part2)
# move(part,dx,dy)
# translate(part,dx,dy,dz)
# rotate(part, angle)
# rotate_x(part, angle)
# rotate_y(part, angle)
# rotate_z(part, angle)
# rotate_90(part)
# rotate_180(part)
# rotate_270(part)
# reflect_x(part)
# reflect_y(part)
# reflect_z(part)
# reflect_xy(part)
# reflect_xz(part)
# reflect_yz(part)
# scale_x(part, x0, sx)
# scale_y(part, y0, sy)
# scale_z(part, z0, sz)
# scale_xy(part, x0, y0, sxy)
# scale_xyz(part, x0, y0, z0, sxyz)
# coscale_x_y(part, x0, y0, y1, angle0, angle1, amplitude, offset)
# coscale_x_z(part, x0, z0, z1, angle0, angle1, amplitude, offset)
# coscale_xy_z(part, x0, y0, z0, z1, angle0, angle1, amplitude, offset)
# taper_x_y(part, x0, y0, y1, s0, s1)
# taper_x_z(part, x0, z0, z1, s0, s1)
# taper_xy_z(part, x0, y0, z0, z1, s0, s1)
# shear_x_y(part, y0, y1, dx0, dx1)
# shear_x_z(part, z0, z1, dx0, dx1)
# (more to come)

def circle(x0, y0, r):
   part = "(((X-x0)**2 + (Y-y0)**2) <= r**2)"
   part = replace(part,'x0',str(x0))
   part = replace(part,'y0',str(y0))
   part = replace(part,'r',str(r))
   return part

def cylinder(x0, y0, z0, z1, r):
   part = "(((X-x0)**2 + (Y-y0)**2 <= r**2) & (Z >= z0) & (Z <= z1))"
   part = replace(part,'x0',str(x0))
   part = replace(part,'y0',str(y0))
   part = replace(part,'z0',str(z0))
   part = replace(part,'z1',str(z1))
   part = replace(part,'r',str(r))
   return part

def cone(x0, y0, z0, z1, r0):
   part = cylinder(x0, y0, z0, z1, r0)
   part = taper_xy_z(part, x0, y0, z0, z1, 1.0, 0.0)
   return part

def sphere(x0, y0, z0, r):
   part = "(((X-x0)**2 + (Y-y0)**2 + (Z-z0)**2) <= r**2)"
   part = replace(part,'x0',str(x0))
   part = replace(part,'y0',str(y0))
   part = replace(part,'z0',str(z0))
   part = replace(part,'r',str(r))
   return part

def torus(x0, y0, z0, r0, r1):
   part = "(((r0 - sqrt((X-x0)**2 + (Y-y0)**2))**2 + (Z-z0)**2) <= r1**2)"
   part = replace(part,'x0',str(x0))
   part = replace(part,'y0',str(y0))
   part = replace(part,'z0',str(z0))
   part = replace(part,'r0',str(r0))
   part = replace(part,'r1',str(r1))
   return part

def rectangle(x0, x1, y0, y1):
   part = "((X >= x0) & (X <= x1) & (Y >= y0) & (Y <= y1))"
   part = replace(part,'x0',str(x0))
   part = replace(part,'x1',str(x1))
   part = replace(part,'y0',str(y0))
   part = replace(part,'y1',str(y1))
   return part

def cube(x0, x1, y0, y1, z0, z1):
   part = "((X >= x0) & (X <= x1) & (Y >= y0) & (Y <= y1) & (Z >= z0) & (Z <= z1))"
   part = replace(part,'x0',str(x0))
   part = replace(part,'x1',str(x1))
   part = replace(part,'y0',str(y0))
   part = replace(part,'y1',str(y1))
   part = replace(part,'z0',str(z0))
   part = replace(part,'z1',str(z1))
   return part

def triangle(x0, y0, x1, y1, x2, y2): # points in clockwise order
   part = "((((y1-y0)*(X-x0)-(x1-x0)*(Y-y0)) >= 0) & (((y2-y1)*(X-x1)-(x2-x1)*(Y-y1)) >= 0) & (((y0-y2)*(X-x2)-(x0-x2)*(Y-y2)) >= 0))"
   part = replace(part,'x0',str(x0))
   part = replace(part,'y0',str(y0))
   part = replace(part,'x1',str(x1))
   part = replace(part,'y1',str(y1))
   part = replace(part,'x2',str(x2))
   part = replace(part,'y2',str(y2))
   return part

def pyramid(x0, x1, y0, y1, z0, z1):
   part = cube(x0, x1, y0, y1, z0, z1)
   part = taper_xy_z(part, (x0+x1)/2., (y0+y1)/2., z0, z1, 1.0, 0.0)
   return part

def function(Z_of_XY):
   part = '(Z <= '+Z_of_XY+')'
   return part

def functions(upper_Z_of_XY,lower_Z_of_XY):
   part = '(Z <= '+upper_Z_of_XY+') & (Z >= '+lower_Z_of_XY+')'
   return part

def add(part1, part2):
   part = "part1 | part2"
   part = replace(part,'part1',part1)
   part = replace(part,'part2',part2)
   return part

def subtract(part1, part2):
   part = "(part1) & ~(part2)"
   part = replace(part,'part1',part1)
   part = replace(part,'part2',part2)
   return part

def intersect(part1, part2):
   part = "(part1) & (part2)"
   part = replace(part,'part1',part1)
   part = replace(part,'part2',part2)
   return part

def move(part,dx,dy):
   part = replace(part,'X','(X-'+str(dx)+')')
   part = replace(part,'Y','(Y-'+str(dy)+')')
   return part   

def translate(part,dx,dy,dz):
   part = replace(part,'X','(X-'+str(dx)+')')
   part = replace(part,'Y','(Y-'+str(dy)+')')
   part = replace(part,'Z','(Z-'+str(dz)+')')
   return part   

def rotate(part, angle):
   angle = angle*pi/180
   part = replace(part,'X','(cos(angle)*X+sin(angle)*y)')
   part = replace(part,'Y','(-sin(angle)*X+cos(angle)*y)')
   part = replace(part,'y','Y')
   part = replace(part,'angle',str(angle))
   return part

def rotate_x(part, angle):
   angle = angle*pi/180
   part = replace(part,'Y','(cos(angle)*Y+sin(angle)*z)')
   part = replace(part,'Z','(-sin(angle)*Y+cos(angle)*z)')
   part = replace(part,'z','Z')
   part = replace(part,'angle',str(angle))
   return part

def rotate_y(part, angle):
   angle = angle*pi/180
   part = replace(part,'X','(cos(angle)*X+sin(angle)*z)')
   part = replace(part,'Z','(-sin(angle)*X+cos(angle)*z)')
   part = replace(part,'z','Z')
   part = replace(part,'angle',str(angle))
   return part

def rotate_z(part, angle):
   angle = angle*pi/180
   part = replace(part,'X','(cos(angle)*X+sin(angle)*y)')
   part = replace(part,'Y','(-sin(angle)*X+cos(angle)*y)')
   part = replace(part,'y','Y')
   part = replace(part,'angle',str(angle))
   return part

def rotate_90(part):
   part = reflect_xy(part)
   part = reflect_y(part)
   return part

def rotate_180(part):
   part = reflect_xy(part)
   part = reflect_y(part)
   part = reflect_xy(part)
   part = reflect_y(part)
   return part

def rotate_270(part):
   part = reflect_xy(part)
   part = reflect_y(part)
   part = reflect_xy(part)
   part = reflect_y(part)
   part = reflect_xy(part)
   part = reflect_y(part)
   return part

def reflect_x(part):
   part = replace(part,'X','-X')
   return part

def reflect_y(part):
   part = replace(part,'Y','-Y')
   return part

def reflect_z(part):
   part = replace(part,'Z','-Z')
   return part

def reflect_xy(part):
   part = replace(part,'X','temp')
   part = replace(part,'Y','X')
   part = replace(part,'temp','Y')
   return part

def reflect_xz(part):
   part = replace(part,'X','temp')
   part = replace(part,'Z','X')
   part = replace(part,'temp','Z')
   return part

def reflect_yz(part):
   part = replace(part,'Y','temp')
   part = replace(part,'Z','Y')
   part = replace(part,'temp','Z')
   return part

def scale_x(part, x0, sx):
   part = replace(part,'X','(x0 + (X-x0)/sx)')
   part = replace(part,'x0',str(x0))
   part = replace(part,'sx',str(sx))
   return part

def scale_y(part, y0, sy):
   part = replace(part,'Y','(y0 + (Y-y0)/sy)')
   part = replace(part,'y0',str(y0))
   part = replace(part,'sy',str(sy))
   return part

def scale_z(part, z0, sz):
   part = replace(part,'Z','(z0 + (Z-z0)/sz)')
   part = replace(part,'z0',str(z0))
   part = replace(part,'sz',str(sz))
   return part

def scale_xy(part, x0, y0, sxy):
   part = replace(part,'X','(x0 + (X-x0)/sxy)')
   part = replace(part,'Y','(y0 + (Y-y0)/sxy)')
   part = replace(part,'x0',str(x0))
   part = replace(part,'y0',str(y0))
   part = replace(part,'sxy',str(sxy))
   return part

def scale_xyz(part, x0, y0, z0, sxyz):
   part = replace(part,'X','(x0 + (X-x0)/sxyz)')
   part = replace(part,'Y','(y0 + (Y-y0)/sxyz)')
   part = replace(part,'Z','(z0 + (Z-z0)/sxyz)')
   part = replace(part,'x0',str(x0))
   part = replace(part,'y0',str(y0))
   part = replace(part,'z0',str(z0))
   part = replace(part,'sxyz',str(sxyz))
   return part

def coscale_x_y(part, x0, y0, y1, angle0, angle1, amplitude, offset):
   phase0 = pi*angle0/180.
   phase1 = pi*angle1/180.
   part = replace(part,'X','(x0 + (X-x0)/(offset + amplitude*cos(phase0 + (phase1-phase0)*(Y-y0)/(y1-y0))))')
   part = replace(part,'x0',str(x0))
   part = replace(part,'y0',str(y0))
   part = replace(part,'y1',str(y1))
   part = replace(part,'phase0',str(phase0))
   part = replace(part,'phase1',str(phase1))
   part = replace(part,'amplitude',str(amplitude))
   part = replace(part,'offset',str(offset))
   return part

def coscale_x_z(part, x0, z0, z1, angle0, angle1, amplitude, offset):
   phase0 = pi*angle0/180.
   phase1 = pi*angle1/180.
   part = replace(part,'X','(x0 + (X-x0)/(offset + amplitude*cos(phase0 + (phase1-phase0)*(Z-z0)/(z1-z0))))')
   part = replace(part,'x0',str(x0))
   part = replace(part,'z0',str(z0))
   part = replace(part,'z1',str(z1))
   part = replace(part,'phase0',str(phase0))
   part = replace(part,'phase1',str(phase1))
   part = replace(part,'amplitude',str(amplitude))
   part = replace(part,'offset',str(offset))
   return part

def coscale_xy_z(part, x0, y0, z0, z1, angle0, angle1, amplitude, offset):
   phase0 = pi*angle0/180.
   phase1 = pi*angle1/180.
   part = replace(part,'X','(x0 + (X-x0)/(offset + amplitude*cos(phase0 + (phase1-phase0)*(Z-z0)/(z1-z0))))')
   part = replace(part,'Y','(y0 + (Y-y0)/(offset + amplitude*cos(phase0 + (phase1-phase0)*(Z-z0)/(z1-z0))))')
   part = replace(part,'x0',str(x0))
   part = replace(part,'y0',str(y0))
   part = replace(part,'z0',str(z0))
   part = replace(part,'z1',str(z1))
   part = replace(part,'phase0',str(phase0))
   part = replace(part,'phase1',str(phase1))
   part = replace(part,'amplitude',str(amplitude))
   part = replace(part,'offset',str(offset))
   return part

def taper_x_y(part, x0, y0, y1, s0, s1):
   part = replace(part,'X','(x0 + (X-x0)*(y1-y0)/(s1*(Y-y0) + s0*(y1-Y)))')
   part = replace(part,'x0',str(x0))
   part = replace(part,'y0',str(y0))
   part = replace(part,'y1',str(y1))
   part = replace(part,'s0',str(s0))
   part = replace(part,'s1',str(s1))
   return part

def taper_x_z(part, x0, z0, z1, s0, s1):
   part = replace(part,'X','(x0 + (X-x0)*(z1-z0)/(s1*(Z-z0) + s0*(z1-Z)))')
   part = replace(part,'x0',str(x0))
   part = replace(part,'z0',str(z0))
   part = replace(part,'z1',str(z1))
   part = replace(part,'s0',str(s0))
   part = replace(part,'s1',str(s1))
   return part

def taper_xy_z(part, x0, y0, z0, z1, s0, s1):
   part = replace(part,'X','(x0 + (X-x0)*(z1-z0)/(s1*(Z-z0) + s0*(z1-Z)))')
   part = replace(part,'Y','(y0 + (Y-y0)*(z1-z0)/(s1*(Z-z0) + s0*(z1-Z)))')
   part = replace(part,'x0',str(x0))
   part = replace(part,'y0',str(y0))
   part = replace(part,'z0',str(z0))
   part = replace(part,'z1',str(z1))
   part = replace(part,'s0',str(s0))
   part = replace(part,'s1',str(s1))
   return part

def shear_x_y(part, y0, y1, dx0, dx1):
   part = replace(part,'X','(X - dx0 - (dx1-dx0)*(Y-y0)/(y1-y0))')
   part = replace(part,'y0',str(y0))
   part = replace(part,'y1',str(y1))
   part = replace(part,'dx0',str(dx0))
   part = replace(part,'dx1',str(dx1))
   return part

def shear_x_z(part, z0, z1, dx0, dx1):
   part = replace(part,'X','(X - dx0 - (dx1-dx0)*(Z-z0)/(z1-z0))')
   part = replace(part,'z0',str(z0))
   part = replace(part,'z1',str(z1))
   part = replace(part,'dx0',str(dx0))
   part = replace(part,'dx1',str(dx1))
   return part

def coshear_x_z(part, z0, z1, angle0, angle1, amplitude, offset):
   phase0 = pi*angle0/180.
   phase1 = pi*angle1/180.
   part = replace(part,'X','(X - offset - amplitude*cos(phase0 + (phase1-phase0)*(Z-z0)/(z1-z0)))')
   part = replace(part,'z0',str(z0))
   part = replace(part,'z1',str(z1))
   part = replace(part,'phase0',str(phase0))
   part = replace(part,'phase1',str(phase1))
   part = replace(part,'amplitude',str(amplitude))
   part = replace(part,'offset',str(offset))
   return part

#
# PCB classes and definitions
#

cad.labels = []

class PCB:
   def __init__(self,x0,y0,width,height,mask):
      self.board = "False"
      self.interior = rectangle(x0,x0+width,y0,y0+height)
      self.exterior = subtract("True",rectangle(x0,x0+width,y0,y0+height))
      self.mask = "False"
   def add(self,part):
      self.board = add(self.board,part)
      self.mask = add(self.mask,move(part,-mask,mask))
      self.mask = add(self.mask,move(part,-mask,-mask))
      self.mask = add(self.mask,move(part,mask,mask))
      self.mask = add(self.mask,move(part,mask,-mask))
      return self

class part:
   def add(self,pcb,x,y,z=0,angle=0):
      self.x = x
      self.y = y
      self.z = z
      self.angle = angle
      if (angle == 90):
         self.shape = rotate_90(self.shape)
      elif (angle == 180):
         self.shape = rotate_180(self.shape)
      elif ((angle == 270) | (angle == -90)):
         self.shape = rotate_270(self.shape)
      angle = pi*angle/180
      self.shape = translate(self.shape,x,y,z)
      for i in range(len(self.pad)):
         xnew = cos(angle)*self.pad[i].x + sin(angle)*self.pad[i].y
         ynew = -sin(angle)*self.pad[i].x + cos(angle)*self.pad[i].y
	 self.pad[i].x = x + xnew
	 self.pad[i].y = y + ynew
         self.pad[i].z += z
      cad.labels.append(cad_text(x,y,z,self.value,size=14))
      for i in range(len(self.labels)):
         xnew = cos(angle)*self.labels[i].x + sin(angle)*self.labels[i].y
         ynew = -sin(angle)*self.labels[i].x + cos(angle)*self.labels[i].y
	 self.labels[i].x = x + xnew
	 self.labels[i].y = y + ynew
         self.labels[i].z += z
	 cad.labels.append(self.labels[i])
      pcb = pcb.add(self.shape)
      return pcb

def wire(pcb,width,*points):
   for i in range(1,len(points)):
      x0 = points[i-1].x
      y0 = points[i-1].y
      z0 = points[i-1].z
      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))
   return pcb

#
# PCB library
#

#
# discretes
#

pad_0402 = cube(-.0175,.0175,-.014,.014,0,0)

class R_0402(part):
   #
   # 0402 resistor
   #
   def __init__(self,value=''):
      self.value = value
      self.labels = []
      self.pad = [point(0,0,0)]
      self.shape = translate(pad_0402,-.0265,0,0)
      self.pad.append(point(-.0265,0,0))
      self.shape = add(self.shape,translate(pad_0402,.0265,0,0))
      self.pad.append(point(.0265,0,0))

pad_1206 = cube(-.032,.032,-.034,.034,0,0)

class R_1206(part):
   #
   # 1206 resistor
   #
   def __init__(self,value=''):
      self.value = value
      self.labels = []
      self.pad = [point(0,0,0)]
      self.shape = translate(pad_1206,-.06,0,0)
      self.pad.append(point(-.06,0,0))
      self.shape = add(self.shape,translate(pad_1206,.06,0,0))
      self.pad.append(point(.06,0,0))

class C_1206(part):
   #
   # 1206 capacitor
   #
   def __init__(self,value=''):
      self.value = value
      self.labels = []
      self.pad = [point(0,0,0)]
      self.shape = translate(pad_1206,-.06,0,0)
      self.pad.append(point(-.06,0,0))
      self.shape = add(self.shape,translate(pad_1206,.06,0,0))
      self.pad.append(point(.06,0,0))

pad_1210 = cube(-.032,.032,-.048,.048,0,0)

class L_1210(part):
   #
   # 1210 inductor
   #
   def __init__(self,value=''):
      self.value = value
      self.labels = []
      self.pad = [point(0,0,0)]
      self.shape = translate(pad_1210,-.06,0,0)
      self.pad.append(point(-.06,0,0))
      self.shape = add(self.shape,translate(pad_1210,.06,0,0))
      self.pad.append(point(.06,0,0))

pad_choke = cube(-.06,.06,-.06,.06,0,0)

class choke(part):
   #
   # Panasonic ELLCTV
   #
   def __init__(self,value=''):
      self.value = value
      self.labels = []
      self.pad = [point(0,0,0)]
      self.shape = translate(pad_choke,-.177,-.177,0)
      self.pad.append(point(-.177,-.177,0))
      self.shape = add(self.shape,translate(pad_choke,.177,.177,0))
      self.pad.append(point(.177,.177,0))

#
# connectors
#

pad_MTA = cube(-.021,.021,-.041,.041,0,0)
pad_MTA_solder = cube(-.071,.071,-.041,.041,0,0)

class MTA_2(part):
   #
   # AMP 1445121-2
   # MTA .050 SMT 2-pin vertical
   #
   def __init__(self,value=''):
      self.value = value
      self.pad = [point(0,0,0)]
      self.labels = []
      #
      # pin 1
      #
      self.shape = translate(pad_MTA,-.025,-.1,0)
      self.pad.append(point(-.025,-.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1',14))
      #
      # pin 2
      #
      self.shape = add(self.shape,translate(pad_MTA,.025,.1,0))
      self.pad.append(point(.025,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'2',14))
      #
      # solder pads
      #
      self.shape = add(self.shape,translate(pad_MTA_solder,-.187,0,0))
      self.shape = add(self.shape,translate(pad_MTA_solder,.187,0,0))

class MTA_power(part):
   #
   # AMP 1445121-2
   # MTA .050 SMT 2-pin vertical
   #
   def __init__(self,value=''):
      self.value = value
      self.pad = [point(0,0,0)]
      self.labels = []
      #
      # pin 1: Gnd
      #
      self.shape = translate(pad_MTA,-.025,-.1,0)
      self.pad.append(point(-.025,-.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1',14))
      #
      # pin 2: Vcc
      #
      self.shape = add(self.shape,translate(pad_MTA,.025,.1,0))
      self.pad.append(point(.025,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Vcc',14))
      #
      # solder pads
      #
      self.shape = add(self.shape,translate(pad_MTA_solder,-.187,0,0))
      self.shape = add(self.shape,translate(pad_MTA_solder,.187,0,0))

class MTA_i0(part):
   #
   # AMP 1445121-3
   # MTA .050 SMT 3-pin vertical
   #
   def __init__(self,value=''):
      self.value = value
      self.pad = [point(0,0,0)]
      self.labels = []
      #
      # pin 1: GND
      #
      self.shape = translate(pad_MTA,.05,.1,0)
      self.pad.append(point(.05,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1\nGND',14))
      #
      # pin 2: power 
      #
      self.shape = add(self.shape,translate(pad_MTA,-.05,.1,0))
      self.pad.append(point(-.05,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V',14))
      #
      # pin 3: data
      #
      self.shape = add(self.shape,translate(pad_MTA,0,-.1,0))
      self.pad.append(point(0,-.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'data',14))
      #
      # solder pads
      #
      self.shape = add(self.shape,translate(pad_MTA_solder,-.212,0,0))
      self.shape = add(self.shape,translate(pad_MTA_solder,.212,0,0))

class MTA_serial(part):
   #
   # AMP 1445121-4
   # MTA .050 SMT 4-pin vertical
   #
   def __init__(self,value=''):
      self.value = value
      self.pad = [point(0,0,0)]
      self.labels = []
      #
      # pin 1: Gnd
      #
      self.shape = translate(pad_MTA,-.075,-.1,0)
      self.pad.append(point(-.075,-.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1',14))
      #
      # pin 2: Tx
      #
      self.shape = add(self.shape,translate(pad_MTA,.025,-.1,0))
      self.pad.append(point(.025,-.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Tx',14))
      #
      # pin 3: Rx
      #
      self.shape = add(self.shape,translate(pad_MTA,.075,.1,0))
      self.pad.append(point(.075,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Rx',14))
      #
      # pin 4: DTR
      #
      self.shape = add(self.shape,translate(pad_MTA,-.025,.1,0))
      self.pad.append(point(-.025,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DTR',14))
      #
      # solder pads
      #
      self.shape = add(self.shape,translate(pad_MTA_solder,-.237,0,0))
      self.shape = add(self.shape,translate(pad_MTA_solder,.237,0,0))

class MTA_ICP(part):
   #
   # AMP 1445121-5
   # MTA .050 SMT 4-pin vertical
   #
   def __init__(self,value=''):
      self.value = value
      self.pad = [point(0,0,0)]
      self.labels = []
      #
      # pin 1: MISO
      #
      self.shape = translate(pad_MTA,-.1,-.1,0)
      self.pad.append(point(-.1,-.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'MISO',14))
      #
      # pin 2: GND
      #
      self.shape = add(self.shape,translate(pad_MTA,0,-.1,0))
      self.pad.append(point(0,-.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',14))
      #
      # pin 3: MOSI
      #
      self.shape = add(self.shape,translate(pad_MTA,.1,-.1,0))
      self.pad.append(point(.1,-.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'MOSI',14))
      #
      # pin 4: -RESET
      #
      self.shape = add(self.shape,translate(pad_MTA,.05,.1,0))
      self.pad.append(point(.05,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'-RESET',14))
      #
      # pin 5: SCK
      #
      self.shape = add(self.shape,translate(pad_MTA,-.05,.1,0))
      self.pad.append(point(-.05,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCK',14))
      #
      # solder pads
      #
      self.shape = add(self.shape,translate(pad_MTA_solder,-.262,0,0))
      self.shape = add(self.shape,translate(pad_MTA_solder,.262,0,0))

class power_65mm(part):
   #
   # CUI PJ1-023-SMT
   #
   def __init__(self,value=''):
      self.value = value
      self.pad = [point(0,0,0)]
      self.labels = []
      #
      # pin 1: power
      #
      self.shape = cube(.433,.512,-.047,.047,0,0)
      self.pad.append(point(.467,0,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'P',14))
      #
      # pin 2: ground
      #
      self.shape = add(self.shape,cube(.285,.423,-.189,-.098,0,0))
      self.pad.append(point(.354,-.144,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G',14))
      #
      # pin 3: contact
      #
      self.shape = add(self.shape,cube(.325,.463,.098,.189,0,0))
      self.pad.append(point(.394,.144,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'C',14))
      #
      # solder pads
      #
      self.shape = add(self.shape,cube(.108,.246,-.169,-.110,0,0))
      self.shape = add(self.shape,cube(.069,.207,.110,.169,0,0))

pad_stereo_2_5mm = cube(-.03,.03,-.05,.05,0,0)

class stereo_2_5mm(part):
   #
   # CUI SJ1-2533-SMT
   #
   def __init__(self,value=''):
      self.value = value
      self.pad = [point(0,0,0)]
      self.labels = []
      #
      # pin 1: base
      #
      self.shape = translate(pad_stereo_2_5mm,-.130,-.16,0)
      self.pad.append(point(-.130,-.149,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'base',14))
      #
      # pin 2: tip
      #
      self.shape = add(self.shape,translate(pad_stereo_2_5mm,.197,.15,0))
      self.pad.append(point(.197,.141,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'tip',14))
      #
      # pin 3: middle
      #
      self.shape = add(self.shape,translate(pad_stereo_2_5mm,-.012,-.16,0))
      self.pad.append(point(-.012,-.149,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'middle',14))

pad_Molex = cube(-.0155,.0155,-.0265,.0265,0,0)
pad_Molex_solder = cube(-.055,.055,-.065,.065,0,0)

class Molex_serial(part):
   #
   # Molex 53261-0471
   #
   def __init__(self,value=''):
      self.value = value
      self.pad = [point(0,0,0)]
      self.labels = []
      #
      # pin 1: Rx
      #
      self.shape = translate(pad_Molex,-.075,.064,0)
      self.pad.append(point(-.075,.064,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Rx',14))
      #
      # pin 2: Tx
      #
      self.shape = add(self.shape,translate(pad_Molex,-.025,.064,0))
      self.pad.append(point(-.025,.064,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Tx',14))
      #
      # pin 3: DTR
      #
      self.shape = add(self.shape,translate(pad_Molex,.025,.064,0))
      self.pad.append(point(.025,.064,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DTR',14))
      #
      # pin 4: GND
      #
      self.shape = add(self.shape,translate(pad_Molex,.075,.064,0))
      self.pad.append(point(.075,.064,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',14))
      #
      # solder pads
      #
      self.shape = add(self.shape,translate(pad_Molex_solder,-.16,-.065,0))
      self.shape = add(self.shape,translate(pad_Molex_solder,.16,-.065,0))

#
# switches
#

pad_button_6mm = cube(-.04,.04,-.03,.03,0,0)

class button_6mm(part):
   # 
   # Omron 6mm pushbutton
   # B3SN-3112P
   #
   def __init__(self,value=''):
      self.value = value
      self.pad = [point(0,0,0)]
      self.labels = []
      #
      # left 1
      #
      self.shape = translate(pad_button_6mm,-.125,.08,0)
      self.pad.append(point(-.125,.08,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'L1',14))
      #
      # right 1
      #
      self.shape = add(self.shape,translate(pad_button_6mm,-.125,-.08,0))
      self.pad.append(point(-.125,-.08,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'R1',14))
      #
      # right 2
      #
      self.shape = add(self.shape,translate(pad_button_6mm,.125,-.08,0))
      self.pad.append(point(.125,-.08,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'R2',14))
      #
      # left 2
      #
      self.shape = add(self.shape,translate(pad_button_6mm,.125,.08,0))
      self.pad.append(point(.125,.08,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'L2',14))

#
# crystals and resonators
#

pad_XTAL = cube(-.016,.016,-.077,.077,0,0)

class XTAL(part):
   #
   # Panasonic EFOBM series
   #
   def __init__(self,value=''):
      self.value = value
      self.pad = [point(0,0,0)]
      self.labels = []
      #
      # left
      #
      self.shape = translate(pad_XTAL,-.053,0,0)
      self.pad.append(point(-.053,0,0))
      #
      # ground
      #
      self.shape = add(self.shape,translate(pad_XTAL,0,0,0))
      self.pad.append(point(0,0,0))
      #
      # right
      #
      self.shape = add(self.shape,translate(pad_XTAL,.053,0,0))
      self.pad.append(point(.053,0,0))

#
# diodes, transistors, regulators
#

class D_1206(part):
   #
   # 1206 diode
   #
   def __init__(self,value=''):
      self.value = value
      self.pad = [point(0,0,0)]
      self.labels = []
      #
      # anode
      #
      self.shape = translate(pad_1206,-.06,0,0)
      self.pad.append(point(-.055,0,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A',14))
      #
      # cathode
      #
      self.shape = add(self.shape,translate(pad_1206,.06,0,0))
      self.pad.append(point(.055,0,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'C',14))

class LED_1206(part):
   #
   # 1206 LED
   #
   def __init__(self,value=''):
      self.value = value
      self.pad = [point(0,0,0)]
      self.labels = []
      #
      # anode
      #
      self.shape = translate(pad_1206,-.06,0,0)
      self.pad.append(point(-.055,0,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A',14))
      #
      # cathode
      #
      self.shape = add(self.shape,translate(pad_1206,.06,0,0))
      self.pad.append(point(.055,0,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'C',14))

class phototransistor_1206(part):
   #
   # 1206 phototransistor
   # OPTEK 520,521
   #
   def __init__(self,value=''):
      self.value = value
      self.pad = [point(0,0,0)]
      self.labels = []
      #
      # collector
      #
      self.shape = translate(pad_1206,-.06,0,0)
      self.pad.append(point(-.055,0,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'C',14))
      #
      # emitter
      #
      self.shape = add(self.shape,translate(pad_1206,.06,0,0))
      self.pad.append(point(.055,0,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'E',14))

pad_SOD_123 = cube(-.02,.02,-.024,.024,0,0)

class D_SOD_123(part):
   #
   # SOD-123 diode
   #
   def __init__(self,value=''):
      self.value = value
      self.pad = [point(0,0,0)]
      self.labels = []
      #
      # anode
      #
      self.shape = translate(pad_SOD_123,-.07,0,0)
      self.pad.append(point(-.07,0,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A',14))
      #
      # cathode
      #
      self.shape = add(self.shape,translate(pad_SOD_123,.07,0,0))
      self.pad.append(point(.07,0,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'C',14))

pad_SOT23 = cube(-.015,.015,-.02,.02,0,0)

class NMOSFET_SOT23(part):
   #
   # Fairchild NDS355AN
   #
   def __init__(self,value=''):
      self.value = value
      self.x = 0
      self.y = 0
      self.z = 0
      self.pad = [point(0,0,0)]
      self.labels = []
      #
      # pin 1: gate
      #
      self.shape = translate(pad_SOT23,-.0375,-.045,0)
      self.pad.append(point(-.0375,-.045,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G',14))
      #
      # pin 2: source
      #
      self.shape = add(self.shape,translate(pad_SOT23,.0375,-.045,0))
      self.pad.append(point(.0375,-.045,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'S',14))
      #
      # pin 3: drain
      #
      self.shape = add(self.shape,translate(pad_SOT23,0,.045,0))
      self.pad.append(point(0,.045,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'D',14))

class PMOSFET_SOT23(part):
   #
   # Fairchild NDS356AP
   #
   def __init__(self,value=''):
      self.value = value
      self.x = 0
      self.y = 0
      self.z = 0
      self.pad = [point(0,0,0)]
      self.labels = []
      #
      # pin 1: gate
      #
      self.shape = translate(pad_SOT23,-.0375,-.045,0)
      self.pad.append(point(-.0375,-.045,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G',14))
      #
      # pin 2: source
      #
      self.shape = add(self.shape,translate(pad_SOT23,.0375,-.045,0))
      self.pad.append(point(.0375,-.045,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'S',14))
      #
      # pin 3: drain
      #
      self.shape = add(self.shape,translate(pad_SOT23,0,.045,0))
      self.pad.append(point(0,.045,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'D',14))

class regulator_SOT23(part):
   def __init__(self,value=''):
      self.value = value
      self.x = 0
      self.y = 0
      self.z = 0
      self.pad = [point(0,0,0)]
      self.labels = []
      #
      # pin 1: output
      #
      self.shape = translate(pad_SOT23,-.0375,-.045,0)
      self.pad.append(point(-.0375,-.045,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1',14))
      #
      # pin 2: input
      #
      self.shape = add(self.shape,translate(pad_SOT23,.0375,-.045,0))
      self.pad.append(point(.0375,-.045,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'in',14))
      #
      # pin 3: ground
      #
      self.shape = add(self.shape,translate(pad_SOT23,0,.045,0))
      self.pad.append(point(0,.045,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'gnd',14))

pad_SOT223 = cube(-.02,.02,-.03,.03,0,0)
pad_SOT223_ground = cube(-.065,.065,-.03,.03,0,0)

class regulator_SOT223(part):
   def __init__(self,value=''):
      self.value = value
      self.x = 0
      self.y = 0
      self.z = 0
      self.pad = [point(0,0,0)]
      self.labels = []
      #
      # pin 1: input
      #
      self.shape = translate(pad_SOT223,-.09,-.12,0)
      self.pad.append(point(-.09,-.12,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1I',14))
      #
      # pin 2: ground
      #
      self.shape = add(self.shape,translate(pad_SOT223,0,-.12,0))
      self.pad.append(point(0,-.12,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G',14))
      #
      # pin 3: output
      #
      self.shape = add(self.shape,translate(pad_SOT223,.09,-.12,0))
      self.pad.append(point(.09,-.12,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'O',14))
      #
      # pin 4: ground
      #
      self.shape = add(self.shape,translate(pad_SOT223_ground,0,.12,0))
      self.pad.append(point(0,.12,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G',14))

pad_SM8 = cube(-.035,.035,-.016,.016,0,0)

class H_bridge_SM8(part):
   #
   # Zetex ZXMHC3A01T8
   #
   def __init__(self,value=''):
      self.value = value
      self.x = 0
      self.y = 0
      self.z = 0
      self.pad = [point(0,0,0)]
      self.labels = []
      d = .13
      #
      # pin 1: G3 (right N gate)
      #
      self.shape = translate(pad_SM8,-d,.09,0)
      self.pad.append(point(-d,.09,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GRN',14))
      #
      # pin 2: S2 S3 (N source)
      #
      self.shape = add(self.shape,translate(pad_SM8,-d,.03,0))
      self.pad.append(point(-d,.03,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SN',14))
      #
      # pin 3: G2 (left N gate)
      #
      self.shape = add(self.shape,translate(pad_SM8,-d,-.03,0))
      self.pad.append(point(-d,-.03,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GLN',14))
      #
      # pin 4: G1 (left P gate)
      #
      self.shape = add(self.shape,translate(pad_SM8,-d,-.09,0))
      self.pad.append(point(-d,-.09,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GLP',14))
      #
      # pin 5: D1 D2 (left drain)
      #
      self.shape = add(self.shape,translate(pad_SM8,d,-.09,0))
      self.pad.append(point(d,-.09,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DL',14))
      #
      # pin 6: S1 S4 (P source)
      #
      self.shape = add(self.shape,translate(pad_SM8,d,-.03,0))
      self.pad.append(point(d,-.03,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SP',14))
      #
      # pin 7: D3 D4 (right drain)
      #
      self.shape = add(self.shape,translate(pad_SM8,d,.03,0))
      self.pad.append(point(d,.03,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DR',14))
      #
      # pin 8: G4 (right N gate)
      #
      self.shape = add(self.shape,translate(pad_SM8,d,.09,0))
      self.pad.append(point(d,.09,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GRP',14))

#
# ICs
#

pad_SOT23_5 = cube(-.01,.01,-.02,.02,0,0)

class op_amp_SOT23_5(part):
   def __init__(self,value=''):
      self.value = value
      self.x = 0
      self.y = 0
      self.z = 0
      self.pad = [point(0,0,0)]
      self.labels = []
      #
      # pin 1: output
      #
      self.shape = translate(pad_SOT23_5,-.0375,-.045,0)
      self.pad.append(point(-.0375,-.045,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'O',14))
      #
      # pin 2: V-
      #
      self.shape = add(self.shape,translate(pad_SOT23_5,0,-.045,0))
      self.pad.append(point(0,-.045,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V-',14))
      #
      # pin 3: I+
      #
      self.shape = add(self.shape,translate(pad_SOT23_5,.0375,-.045,0))
      self.pad.append(point(.0375,-.045,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'I+',14))
      #
      # pin 4: I-
      #
      self.shape = add(self.shape,translate(pad_SOT23_5,.0375,.045,0))
      self.pad.append(point(.0375,.045,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'I-',14))
      #
      # pin 5: V+
      #
      self.shape = add(self.shape,translate(pad_SOT23_5,-.0375,.045,0))
      self.pad.append(point(-.0375,.045,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V+',14))

pad_SOICN = cube(-.035,.035,-.015,.015,0,0)

class op_amp_SOICN(part):
   def __init__(self,value=''):
      self.value = value
      self.pad = [point(0,0,0)]
      self.labels = []
      #
      # pin 1: A out
      #
      self.shape = translate(pad_SOICN,-.12,.075,0)
      self.pad.append(point(-.12,.075,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1 Ao',14))
      #
      # pin 2: A-
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,.025,0))
      self.pad.append(point(-.12,.025,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A-',14))
      #
      # pin 3: A+
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,-.025,0))
      self.pad.append(point(-.12,-.025,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A+',14))
      #
      # pin 4: V-
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,-.075,0))
      self.pad.append(point(-.12,-.075,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V-',14))
      #
      # pin 5: B+
      #
      self.shape = add(self.shape,translate(pad_SOICN,.12,-.075,0))
      self.pad.append(point(.12,-.075,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'B+',14))
      #
      # pin 6: B-
      #
      self.shape = add(self.shape,translate(pad_SOICN,.12,-.025,0))
      self.pad.append(point(.12,-.025,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'B-',14))
      #
      # pin 7: B out
      #
      self.shape = add(self.shape,translate(pad_SOICN,.12,.025,0))
      self.pad.append(point(.12,.025,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Bo',14))
      #
      # pin 8: V+
      #
      self.shape = add(self.shape,translate(pad_SOICN,.12,.075,0))
      self.pad.append(point(.12,.075,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V+',14))

pad_SOIC = cube(-.043,.043,-.015,.015,0,0)

class ATtiny45_SOIC(part):
   def __init__(self,value=''):
      self.value = value
      self.pad = [point(0,0,0)]
      self.labels = []
      #
      # pin 1: PB5/dW/ADC0/-RESET/PCINT5
      #
      self.shape = translate(pad_SOIC,-.14,.075,0)
      self.pad.append(point(-.14,.075,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1',14))
      #
      # pin 2: PB3/ADC3/-OC1B/CLKI/XTAL1/PCINT3
      #
      self.shape = add(self.shape,translate(pad_SOIC,-.14,.025,0))
      self.pad.append(point(-.14,.025,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB3',14))
      #
      # pin 3: PB4/ADC2/OC1B/CLKO/XTAL2/PCINT4
      #
      self.shape = add(self.shape,translate(pad_SOIC,-.14,-.025,0))
      self.pad.append(point(-.14,-.025,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB4',14))
      #
      # pin 4: GND
      #
      self.shape = add(self.shape,translate(pad_SOIC,-.14,-.075,0))
      self.pad.append(point(-.14,-.075,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',14))
      #
      # pin 5: PB0/MOSI/DI/SDA/AIN0/OC0A/-OC1A/AREF/PCINT0
      #
      self.shape = add(self.shape,translate(pad_SOIC,.14,-.075,0))
      self.pad.append(point(.14,-.075,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0',14))
      #
      # pin 6: PB1/MISO/DO/AIN1/OC0B/OC1A/PCINT1
      #
      self.shape = add(self.shape,translate(pad_SOIC,.14,-.025,0))
      self.pad.append(point(.14,-.025,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB1',14))
      #
      # pin 7: PB2/SCK/USCK/SCL/ADC1/T0/INT0/PCINT2
      #
      self.shape = add(self.shape,translate(pad_SOIC,.14,.025,0))
      self.pad.append(point(.14,.025,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB2',14))
      #
      # pin 8: VCC
      #
      self.shape = add(self.shape,translate(pad_SOIC,.14,.075,0))
      self.pad.append(point(.14,.075,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC',14))

class ATtiny44_SOICN(part):
   def __init__(self,value=''):
      self.value = value
      self.pad = [point(0,0,0)]
      self.labels = []
      #
      # pin 1: VCC
      #
      self.shape = translate(pad_SOICN,-.12,.15,0)
      self.pad.append(point(-.12,.15,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1',14))
      #
      # pin 2: PB0/XTAL1/PCINT8
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,.1,0))
      self.pad.append(point(-.12,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0',14))
      #
      # pin 3: PB1/XTAL2/PCINT9
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,.050,0))
      self.pad.append(point(-.12,.05,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB1',14))
      #
      # pin 4: PB3/dW/-RESET/PCINT11
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,0,0))
      self.pad.append(point(-.12,0,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB3',14))
      #
      # pin 5: PB2/CKOUT/OC0A/INT0/PCINT10
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,-.05,0))
      self.pad.append(point(-.12,-.05,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB2',14))
      #
      # pin 6: PA7/ADC7/OC0B/ICP/PCINT7
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,-.1,0))
      self.pad.append(point(-.12,-.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA7',14))
      #
      # pin 7: PA6/ADC6/MOSI/SDA/OC1A/PCINT6
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,-.15,0))
      self.pad.append(point(-.12,-.15,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA6',14))
      #
      # pin 8: PA5/ADC5/DO/MISO/OC1B/PCINT5
      #
      self.shape = add(self.shape,translate(pad_SOICN,.12,-.15,0))
      self.pad.append(point(.12,-.15,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA5',14))
      #
      # pin 9: PA4/ADC4/USCK/SCL/T1/PCINT4
      #
      self.shape = add(self.shape,translate(pad_SOICN,.12,-.1,0))
      self.pad.append(point(.12,-.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA4',14))
      #
      # pin 10: PA3/ADC3/T0/PCINT3
      #
      self.shape = add(self.shape,translate(pad_SOICN,.12,-.05,0))
      self.pad.append(point(.12,-.05,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA3',14))
      #
      # pin 11: PA2/ADC2/AIN1/PCINT2
      #
      self.shape = add(self.shape,translate(pad_SOICN,.12,0,0))
      self.pad.append(point(.12,0,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA2',14))
      #
      # pin 12: PA1/ADC1/AIN0/PCINT1
      #
      self.shape = add(self.shape,translate(pad_SOICN,.12,.050,0))
      self.pad.append(point(.12,.05,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA1',14))
      #
      # pin 13: PA0/ADC0/AREF/PCINT0
      #
      self.shape = add(self.shape,translate(pad_SOICN,.12,.1,0))
      self.pad.append(point(.12,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA0',14))
      #
      # pin 14: GND
      #
      self.shape = add(self.shape,translate(pad_SOICN,.12,.15,0))
      self.pad.append(point(.12,.15,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',14))

pad_TQFP = cube(-.043,.043,-.015,.015,0,0)

class ATmega88_TQFP(part):
   def __init__(self,value=''):
      self.value = value
      self.pad = [point(0,0,0)]
      self.labels = []

      #
      # pin 1: PD3/PCINT19/OC2B/INT1
      #
      self.shape = translate(pad_SOICN,-.12,.15,0)
      self.pad.append(point(-.12,.15,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1',14))
      #
      # pin 2: PD4/PCINT20/XCK/T0
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,.1,0))
      self.pad.append(point(-.12,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0',14))
      #
      # pin 3: GND
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,.1,0))
      self.pad.append(point(-.12,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0',14))
      #
      # pin 4: VCC
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,.1,0))
      self.pad.append(point(-.12,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0',14))
      #
      # pin 5: GND
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,.1,0))
      self.pad.append(point(-.12,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0',14))
      #
      # pin 6: VCC
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,.1,0))
      self.pad.append(point(-.12,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0',14))
      #
      # pin 7: PB6/PCINT6/XTAL1/TOSC1
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,.1,0))
      self.pad.append(point(-.12,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0',14))
      #
      # pin 8: PB7/PCINT7/XTAL2/TOSC2
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,.1,0))
      self.pad.append(point(-.12,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0',14))

      #
      # pin 9: PD5/PCINT21/OC0B/T1
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,.1,0))
      self.pad.append(point(-.12,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0',14))
      #
      # pin 10: PD6/PCINT22/OC0A/AIN0
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,.1,0))
      self.pad.append(point(-.12,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0',14))
      #
      # pin 11: PD7/PCINT23/AIN1
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,.1,0))
      self.pad.append(point(-.12,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0',14))
      #
      # pin 12: PB0/PCINT0/CLKO/ICP1
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,.1,0))
      self.pad.append(point(-.12,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0',14))
      #
      # pin 13: PB1/PCINT1/OC1A
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,.1,0))
      self.pad.append(point(-.12,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0',14))
      #
      # pin 14: PB2/PCINT2/-SS/OC1B
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,.1,0))
      self.pad.append(point(-.12,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0',14))
      #
      # pin 15: PB3/PCINT3/OC2A/MOSI
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,.1,0))
      self.pad.append(point(-.12,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0',14))
      #
      # pin 16: PB4/PCINT4/MISO
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,.1,0))
      self.pad.append(point(-.12,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0',14))

      #
      # pin 17: PB5/SCK/PCINT5
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,.1,0))
      self.pad.append(point(-.12,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0',14))
      #
      # pin 18: AVCC
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,.1,0))
      self.pad.append(point(-.12,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0',14))
      #
      # pin 19: ADC6
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,.1,0))
      self.pad.append(point(-.12,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0',14))
      #
      # pin 20: AREF
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,.1,0))
      self.pad.append(point(-.12,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0',14))
      #
      # pin 21: GND
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,.1,0))
      self.pad.append(point(-.12,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0',14))
      #
      # pin 22: ADC7
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,.1,0))
      self.pad.append(point(-.12,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0',14))
      #
      # pin 23: PC0/ADC0/PCINT8
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,.1,0))
      self.pad.append(point(-.12,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0',14))
      #
      # pin 24: PC1/ADC1/PCINT9
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,.1,0))
      self.pad.append(point(-.12,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0',14))

      #
      # pin 25: PC2/ADC2/PCINT10
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,.1,0))
      self.pad.append(point(-.12,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0',14))
      #
      # pin 26: PC2/ADC3/PCINT11
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,.1,0))
      self.pad.append(point(-.12,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0',14))
      #
      # pin 27: PC4/ADC4/SDA/PCINT12
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,.1,0))
      self.pad.append(point(-.12,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0',14))
      #
      # pin 28: PC5/ADC5/SCL/PCINT13
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,.1,0))
      self.pad.append(point(-.12,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0',14))
      #
      # pin 29: PC6/-RESET/PCINT14
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,.1,0))
      self.pad.append(point(-.12,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0',14))
      #
      # pin 30: PD0/RXD/PCINT16
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,.1,0))
      self.pad.append(point(-.12,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0',14))
      #
      # pin 31: PD1/TXD/PCINT17
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,.1,0))
      self.pad.append(point(-.12,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0',14))
      #
      # pin 32: PD2/INT0/PCINT18
      #
      self.shape = add(self.shape,translate(pad_SOICN,-.12,.1,0))
      self.pad.append(point(-.12,.1,0))
      self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0',14))

#
# graphics
#

class CBA(part):
   def __init__(self,r=.02):
      self.value = ''
      self.pad = [point(0,0,0)]
      self.labels = []
      d = 3*r
      self.shape = circle(0,0,r)
      self.shape = add(self.shape,translate(circle(0,0,r),-d,d,0))
      self.shape = add(self.shape,translate(rectangle(-r,r,-r,r),-d,0,0))
      self.shape = add(self.shape,translate(rectangle(-r,r,-r,r),-d,-d,0))
      self.shape = add(self.shape,translate(rectangle(-r,r,-r,r),0,-d,0))
      self.shape = add(self.shape,translate(rectangle(-r,r,-r,r),d,-d,0))
      self.shape = add(self.shape,translate(rectangle(-r,r,-r,r),d,0,0))
      self.shape = add(self.shape,translate(rectangle(-r,r,-r,r),d,d,0))
      self.shape = add(self.shape,translate(rectangle(-r,r,-r,r),0,d,0))

class hello(part):
   #
   # HELLO
   #
   def __init__(self,w,z):
      self.value = ''
      self.pad = [point(0,0,0)]
      self.labels = []
      # H
      self.shape = rectangle(-.01,.01,0,.1)
      self.shape = add(self.shape,rectangle(0,.05,.04,.06))
      self.shape = add(self.shape,rectangle(.04,.06,0,.1))
      # E
      self.shape = add(self.shape,rectangle(.08,.1,0,.1))
      self.shape = add(self.shape,rectangle(.1,.14,0,.02))
      self.shape = add(self.shape,rectangle(.1,.13,.04,.06))
      self.shape = add(self.shape,rectangle(.1,.14,.08,.1))
      # L
      self.shape = add(self.shape,rectangle(.16,.18,0,.1))
      self.shape = add(self.shape,rectangle(.18,.21,0,.02))
      # L
      self.shape = add(self.shape,rectangle(.23,.25,0,.1))
      self.shape = add(self.shape,rectangle(.25,.28,0,.02))
      # 0
      self.shape = add(self.shape,rectangle(.3,.32,0,.1))
      self.shape = add(self.shape,rectangle(.32,.345,0,.02))
      self.shape = add(self.shape,rectangle(.32,.345,.08,.1))
      self.shape = add(self.shape,rectangle(.345,.365,0,.1))

#
# define board
#

x0 = 1
y0 = 1
width = 1.23
height = .7
z = -.005
w = .018
mask = .004

pcb = PCB(x0,y0,width,height,mask)

IC1 = ATtiny45_SOIC('IC1\nt45')
pcb = IC1.add(pcb,x0+.76,y0+.35,z,angle=-90)

R1 = R_1206('R1\n10k')
pcb = R1.add(pcb,IC1.pad[1].x-.09,IC1.y,z,angle=90)

pcb = wire(pcb,w,
   IC1.pad[1],
   R1.pad[2])

pcb = wire(pcb,w,
   IC1.pad[8],
   R1.pad[1])

IC2 = regulator_SOT23('IC2\n5V')
pcb = IC2.add(pcb,R1.x-.22,IC1.y+.08,z,angle=180)

C1 = C_1206('C1\n3.3uF')
pcb = C1.add(pcb,IC2.x+.12,IC2.y,z,angle=90)

pcb = wire(pcb,w,
   IC2.pad[1],
   C1.pad[1])

pcb = wire(pcb,w,
   C1.pad[1],
   R1.pad[1])

J1 = MTA_serial('J1')
pcb = J1.add(pcb,IC2.x-.22,IC1.y,z,angle=-90)

pcb = wire(pcb,w,
   J1.pad[1],
   IC2.pad[3])

pcb = wire(pcb,w,
   J1.pad[1],
   C1.pad[2])

pcb = wire(pcb,w,
   J1.pad[3],
   point(J1.pad[3].x,J1.pad[3].y+.05,z),
   point(J1.pad[2].x,IC1.pad[7].y+.06,z),
   point(IC1.pad[8].x-.05,IC1.pad[7].y+.18,z),
   IC1.pad[7])

pcb = wire(pcb,w,
   IC2.pad[2],
   point(IC2.pad[2].x,J1.pad[3].y,z),
   point(J1.x-.02,J1.pad[4].y,z),
   J1.pad[4])

J2 = MTA_ICP('J2')
pcb = J2.add(pcb,IC1.x+.31,IC1.y,z,angle=90)

pcb = wire(pcb,w,
   IC1.pad[6],
   point(IC1.pad[6].x,IC1.pad[6].y+.1,z),
   point(J2.pad[1].x-.03,J2.pad[1].y,z),
   J2.pad[1])

pcb = wire(pcb,w,
   J2.pad[2],
   C1.pad[2])

pcb = wire(pcb,w,
   J2.pad[3],
   point(J2.x,J2.pad[5].y,z),
   IC1.pad[5])

pcb = wire(pcb,w,
   J2.pad[4],
   point(J2.pad[4].x,J2.pad[3].y-.05,z),
   point(J2.pad[3].x-.08,R1.pad[2].y,z),
   IC1.pad[1])

pcb = wire(pcb,w,
   IC1.pad[7],
   point(IC1.pad[7].x,IC1.pad[7].y+.18,z),
   point(J2.pad[1].x+.02,J2.pad[1].y+.05,z),
   J2.pad[5])

R2 = R_1206('R2\n4.99k')
pcb = R2.add(pcb,IC2.pad[3].x+.05,J1.pad[1].y-.08,z)

pcb = wire(pcb,w,
   J1.pad[2],
   point(J1.x+.02,J1.pad[1].y-.05,z),
   point(J1.pad[1].x,R2.y,z),
   R2.pad[1])

D1 = D_SOD_123('D1\n4.7V')
pcb = D1.add(pcb,R2.x,R2.y-.1,z)

pcb = wire(pcb,w,
   D1.pad[1],
   point(D1.x,D1.y,z))

pcb = wire(pcb,w,
   D1.pad[2],
   IC1.pad[2])

pcb = wire(pcb,w,
   D1.pad[2],
   R2.pad[2])

pcb = wire(pcb,w,
   J1.pad[1],
   point(D1.x,D1.y-.06,z),
   IC1.pad[4])

H1 = hello(w,z)
pcb = H1.add(pcb,x0+.23,y0+height-.12,z)

#
# assign board and exterior to cad.function for milling
#
# use single-sided FR2
# use 1/64 end-mill
# set tool diameter = .0156
# set xy, z speed = 4
# set # contours = -1
#

cad.function = add(pcb.board,pcb.exterior)

#
# uncomment to export traces
#

#cad.function = pcb.board

#
# uncomment to export exterior
#

#cad.function = pcb.exterior

#
# uncomment to export solder mask
#

#cad.function = pcb.mask

#
# uncomment to mill out board
#
# use 1/32 end-mill
# set tool diameter = .0312
# set xy, z speed = .5
# set # contours = 1
#

#cad.function = pcb.interior
#z = -.065

#
# define limits and parameters
#

d = 0.05
cad.xmin = x0-d # min x to render
cad.xmax = x0+width+d # max x to render
cad.ymin = y0-d # min y to render
cad.ymax = y0+height+d # max y to render
cad.zmin = z
cad.zmax = .050
dpi = 200 # low resolution for previewing
#dpi = 500 # high resolution for machining
nxy = int(dpi*(cad.xmax-cad.xmin))
cad.nx = int(dpi*(cad.xmax-cad.xmin)) # x points to render
cad.ny = int(dpi*(cad.ymax-cad.ymin)) # y points to render
cad.nz = 1
cad.inches_per_unit = 1.0 # use inch units
cad.view('xy') # 2D view

