From afa7e13b9778dabc4fd8bb4e9e55d8d577d3f6ed Mon Sep 17 00:00:00 2001
From: Quentin Bolsee <quentinbolsee@hotmail.com>
Date: Mon, 17 Jan 2022 17:29:52 +0100
Subject: [PATCH] Added serialstep DRV8428P

---
 serialstep/board/hello.DRV8428-D11C-NEMA17    | 8378 +++++++++++++++++
 .../board/hello.DRV8428-D11C-NEMA17.holes.png |  Bin 0 -> 17614 bytes
 .../hello.DRV8428-D11C-NEMA17.interior.png    |  Bin 0 -> 16144 bytes
 .../board/hello.DRV8428-D11C-NEMA17.png       |  Bin 0 -> 84778 bytes
 .../hello.DRV8428-D11C-NEMA17.traces.png      |  Bin 0 -> 23877 bytes
 .../board/hello.DRV8428P-D11C-NEMA17          | 8371 ++++++++++++++++
 .../hello.DRV8428P-D11C-NEMA17.holes.png      |  Bin 0 -> 21455 bytes
 .../hello.DRV8428P-D11C-NEMA17.interior.png   |  Bin 0 -> 20296 bytes
 .../board/hello.DRV8428P-D11C-NEMA17.png      |  Bin 0 -> 56114 bytes
 .../hello.DRV8428P-D11C-NEMA17.traces.png     |  Bin 0 -> 23212 bytes
 10 files changed, 16749 insertions(+)
 create mode 100644 serialstep/board/hello.DRV8428-D11C-NEMA17
 create mode 100644 serialstep/board/hello.DRV8428-D11C-NEMA17.holes.png
 create mode 100644 serialstep/board/hello.DRV8428-D11C-NEMA17.interior.png
 create mode 100644 serialstep/board/hello.DRV8428-D11C-NEMA17.png
 create mode 100644 serialstep/board/hello.DRV8428-D11C-NEMA17.traces.png
 create mode 100644 serialstep/serialstep-DRV8428P/board/hello.DRV8428P-D11C-NEMA17
 create mode 100644 serialstep/serialstep-DRV8428P/board/hello.DRV8428P-D11C-NEMA17.holes.png
 create mode 100644 serialstep/serialstep-DRV8428P/board/hello.DRV8428P-D11C-NEMA17.interior.png
 create mode 100644 serialstep/serialstep-DRV8428P/board/hello.DRV8428P-D11C-NEMA17.png
 create mode 100644 serialstep/serialstep-DRV8428P/board/hello.DRV8428P-D11C-NEMA17.traces.png

diff --git a/serialstep/board/hello.DRV8428-D11C-NEMA17 b/serialstep/board/hello.DRV8428-D11C-NEMA17
new file mode 100644
index 0000000..e2164e8
--- /dev/null
+++ b/serialstep/board/hello.DRV8428-D11C-NEMA17
@@ -0,0 +1,8378 @@
+#!/usr/bin/env python3
+#
+# hello.DRV8428-D11C-NEMA17
+#    DRV8428 NEMA17 stepper hello-world with D11C interface
+#
+# usage:
+#    hello.DRV8428-D11C-NEMA17 | frep.py [dpi [filename]]
+#
+# Neil Gershenfeld 8/13/21
+#
+# This work may be reproduced, modified, distributed,
+# performed, and displayed for any purpose, but must
+# acknowledge this project. Copyright is retained and
+# must be preserved. The work is provided as is; no
+# warranty is provided, and users accept all liability.
+#
+
+############################################################
+# uncomment for desired output
+############################################################
+
+#output = "top, labels, and exterior"
+output = "top, labels, holes, 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 = "solder mask"
+
+############################################################
+# import
+############################################################
+
+import math,json,sys
+
+############################################################
+# define shapes and transformations
+############################################################
+
+# color(color,part)
+# circle(x,y,r)
+# cylinder(x,y,z0,z1,r)
+# cone(x,y,z0,z1,r)
+# sphere(x,y,z,r)
+# torus(x,y,z,r0,r1)
+# rectangle(x0,x1,y0,y1)
+# cube(x0,x1,y0,y1,z0,z1)
+# line(x0,y0,x1,y1,z,width)
+# right_triangle(x,y,h)
+# 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,x0)
+# reflect_y(part,y0)
+# reflect_z(part,z0)
+# 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)
+
+true = "1"
+false = "0"
+
+def color(color,part):
+   part = '('+str(color)+'*(('+part+')!=0))'
+   return part
+
+Red = (225 << 0)
+Green = (225 << 8)
+Blue = (225 << 16)
+Gray = (128 << 16) + (128 << 8) + (128 << 0)
+White = (255 << 16) + (255 << 8) + (255 << 0)
+Teal = (255 << 16) + (255 << 8)
+Pink = (255 << 16) + (255 << 0)
+Yellow = (255 << 8) + (255 << 0)
+Brown = (45 << 16) + (82 << 8) + (145 << 0)
+Navy = (128 << 16) + (0 << 8) + (0 << 0)
+Tan = (60 << 16) + (90 << 8) + (125 << 0)
+
+def circle(x0,y0,r):
+   part = "(((X-(x0))*(X-(x0)) + (Y-(y0))*(Y-(y0))) <= (r*r))"
+   part = part.replace('x0',str(x0))
+   part = part.replace('y0',str(y0))
+   part = part.replace('r',str(r))
+   return part
+
+def cylinder(x0,y0,z0,z1,r):
+   part = "(((X-(x0))*(X-(x0)) + (Y-(y0))*(Y-(y0)) <= (r*r)) & (Z >= (z0)) & (Z <= (z1)))"
+   part = part.replace('x0',str(x0))
+   part = part.replace('y0',str(y0))
+   part = part.replace('z0',str(z0))
+   part = part.replace('z1',str(z1))
+   part = part.replace('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))*(X-(x0)) + (Y-(y0))*(Y-(y0)) + (Z-(z0))*(Z-(z0))) <= (r*r))"
+   part = part.replace('x0',str(x0))
+   part = part.replace('y0',str(y0))
+   part = part.replace('z0',str(z0))
+   part = part.replace('r',str(r))
+   return part
+
+def torus(x0,y0,z0,r0,r1):
+   part = "(((r0 - sqrt((X-(x0))*(X-(x0)) + (Y-(y0))*(Y-(y0))))*(r0 - sqrt((X-(x0))*(X-(x0)) + (Y-(y0))*(Y-(y0))) + (Z-(z0))*(Z-(z0))) <= (r1*r1))"
+   part = part.replace('x0',str(x0))
+   part = part.replace('y0',str(y0))
+   part = part.replace('z0',str(z0))
+   part = part.replace('r0',str(r0))
+   part = part.replace('r1',str(r1))
+   return part
+
+def rectangle(x0,x1,y0,y1):
+   part = "((X >= (x0)) & (X <= (x1)) & (Y >= (y0)) & (Y <= (y1)))"
+   part = part.replace('x0',str(x0))
+   part = part.replace('x1',str(x1))
+   part = part.replace('y0',str(y0))
+   part = part.replace('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 = part.replace('x0',str(x0))
+   part = part.replace('x1',str(x1))
+   part = part.replace('y0',str(y0))
+   part = part.replace('y1',str(y1))
+   part = part.replace('z0',str(z0))
+   part = part.replace('z1',str(z1))
+   return part
+
+def line(x0,y0,x1,y1,z,width):
+   dx = x1-x0
+   dy = y1-y0
+   l = math.sqrt(dx*dx+dy*dy)
+   nx = dx/l
+   ny = dy/l
+   rx = -ny
+   ry = nx
+   part = "((((X-(x0))*(nx)+(Y-(y0))*(ny)) >= 0) & (((X-(x0))*(nx)+(Y-(y0))*(ny)) <= l) & (((X-(x0))*(rx)+(Y-(y0))*(ry)) >= (-width/2)) & (((X-(x0))*(rx)+(Y-(y0))*(ry)) <= (width/2)) & (Z == z))"
+   part = part.replace('x0',str(x0))
+   part = part.replace('x1',str(x1))
+   part = part.replace('y0',str(y0))
+   part = part.replace('y1',str(y1))
+   part = part.replace('nx',str(nx))
+   part = part.replace('ny',str(ny))
+   part = part.replace('rx',str(rx))
+   part = part.replace('ry',str(ry))
+   part = part.replace('l',str(l))
+   part = part.replace('z',str(z))
+   part = part.replace('width',str(width))
+   return part
+
+def right_triangle(x0,y0,l):
+   part = "((X > x0) & (X < x0 + l - (Y-y0)) & (Y > y0))"
+   part = part.replace('x0',str(x0))
+   part = part.replace('y0',str(y0))
+   part = part.replace('l',str(l))
+   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 = part.replace('x0',str(x0))
+   part = part.replace('y0',str(y0))
+   part = part.replace('x1',str(x1))
+   part = part.replace('y1',str(y1))
+   part = part.replace('x2',str(x2))
+   part = part.replace('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 = part.replace('part1',part1)
+   part = part.replace('part2',part2)
+   return part
+
+def subtract(part1,part2):
+   part = "(part1) & ~(part2)"
+   part = part.replace('part1',part1)
+   part = part.replace('part2',part2)
+   return part
+
+def intersect(part1,part2):
+   part = "(part1) & (part2)"
+   part = part.replace('part1',part1)
+   part = part.replace('part2',part2)
+   return part
+
+def move(part,dx,dy):
+   part = part.replace('X','(X-('+str(dx)+'))')
+   part = part.replace('Y','(Y-('+str(dy)+'))')
+   return part   
+
+def translate(part,dx,dy,dz):
+   part = part.replace('X','(X-('+str(dx)+'))')
+   part = part.replace('Y','(Y-('+str(dy)+'))')
+   part = part.replace('Z','(Z-('+str(dz)+'))')
+   return part   
+
+def rotate(part,angle):
+   angle = angle*math.pi/180
+   part = part.replace('X','(math.cos(angle)*X+math.sin(angle)*y)')
+   part = part.replace('Y','(-math.sin(angle)*X+math.cos(angle)*y)')
+   part = part.replace('y','Y')
+   part = part.replace('angle',str(angle))
+   return part
+
+def rotate_x(part,angle):
+   angle = angle*math.pi/180
+   part = part.replace('Y','(math.cos(angle)*Y+math.sin(angle)*z)')
+   part = part.replace('Z','(-math.sin(angle)*Y+math.cos(angle)*z)')
+   part = part.replace('z','Z')
+   part = part.replace('angle',str(angle))
+   return part
+
+def rotate_y(part,angle):
+   angle = angle*math.pi/180
+   part = part.replace('X','(math.cos(angle)*X+math.sin(angle)*z)')
+   part = part.replace('Z','(-math.sin(angle)*X+math.cos(angle)*z)')
+   part = part.replace('z','Z')
+   part = part.replace('angle',str(angle))
+   return part
+
+def rotate_z(part,angle):
+   angle = angle*math.pi/180
+   part = part.replace('X','(math.cos(angle)*X+math.sin(angle)*y)')
+   part = part.replace('Y','(-math.sin(angle)*X+math.cos(angle)*y)')
+   part = part.replace('y','Y')
+   part = part.replace('angle',str(angle))
+   return part
+
+def rotate_90(part):
+   part = reflect_y(part,0)
+   part = reflect_xy(part)
+   return part
+
+def rotate_180(part):
+   part = rotate_90(part)
+   part = rotate_90(part)
+   return part
+
+def rotate_270(part):
+   part = rotate_90(part)
+   part = rotate_90(part)
+   part = rotate_90(part)
+   return part
+
+def reflect_x(part,x0):
+   part = part.replace('X','(x0-X)')
+   part = part.replace('x0',str(x0))
+   return part
+
+def reflect_y(part,y0):
+   part = part.replace('Y','(y0-Y)')
+   part = part.replace('y0',str(y0))
+   return part
+
+def reflect_z(part,z0):
+   part = part.replace('Z','(z0-Z)')
+   part = part.replace('z0',str(z0))
+   return part
+
+def reflect_xy(part):
+   part = part.replace('X','temp')
+   part = part.replace('Y','X')
+   part = part.replace('temp','Y')
+   return part
+
+def reflect_xz(part):
+   part = part.replace('X','temp')
+   part = part.replace('Z','X')
+   part = part.replace('temp','Z')
+   return part
+
+def reflect_yz(part):
+   part = part.replace('Y','temp')
+   part = part.replace('Z','Y')
+   part = part.replace('temp','Z')
+   return part
+
+def scale_x(part,x0,sx):
+   part = part.replace('X','((x0) + (X-(x0))/(sx))')
+   part = part.replace('x0',str(x0))
+   part = part.replace('sx',str(sx))
+   return part
+
+def scale_y(part,y0,sy):
+   part = part.replace('Y','((y0) + (Y-(y0))/(sy))')
+   part = part.replace('y0',str(y0))
+   part = part.replace('sy',str(sy))
+   return part
+
+def scale_z(part,z0,sz):
+   part = part.replace('Z','((z0) + (Z-(z0))/(sz))')
+   part = part.replace('z0',str(z0))
+   part = part.replace('sz',str(sz))
+   return part
+
+def scale_xy(part,x0,y0,sxy):
+   part = part.replace('X','((x0) + (X-(x0))/(sxy))')
+   part = part.replace('Y','((y0) + (Y-(y0))/(sxy))')
+   part = part.replace('x0',str(x0))
+   part = part.replace('y0',str(y0))
+   part = part.replace('sxy',str(sxy))
+   return part
+
+def scale_xyz(part,x0,y0,z0,sxyz):
+   part = part.replace('X','((x0) + (X-(x0))/(sxyz))')
+   part = part.replace('Y','((y0) + (Y-(y0))/(sxyz))')
+   part = part.replace('Z','((z0) + (Z-(z0))/(sxyz))')
+   part = part.replace('x0',str(x0))
+   part = part.replace('y0',str(y0))
+   part = part.replace('z0',str(z0))
+   part = part.replace('sxyz',str(sxyz))
+   return part
+
+def coscale_x_y(part,x0,y0,y1,angle0,angle1,amplitude,offset):
+   phase0 = math.pi*angle0/180.
+   phase1 = math.pi*angle1/180.
+   part = part.replace('X','((x0) + (X-(x0))/((offset) + (amplitude)*math.cos((phase0) + ((phase1)-(phase0))*(Y-(y0))/((y1)-(y0)))))')
+   part = part.replace('x0',str(x0))
+   part = part.replace('y0',str(y0))
+   part = part.replace('y1',str(y1))
+   part = part.replace('phase0',str(phase0))
+   part = part.replace('phase1',str(phase1))
+   part = part.replace('amplitude',str(amplitude))
+   part = part.replace('offset',str(offset))
+   return part
+
+def coscale_x_z(part,x0,z0,z1,angle0,angle1,amplitude,offset):
+   phase0 = math.pi*angle0/180.
+   phase1 = math.pi*angle1/180.
+   part = part.replace('X','((x0) + (X-(x0))/((offset) + (amplitude)*math.cos((phase0) + ((phase1)-(phase0))*(Z-(z0))/((z1)-(z0)))))')
+   part = part.replace('x0',str(x0))
+   part = part.replace('z0',str(z0))
+   part = part.replace('z1',str(z1))
+   part = part.replace('phase0',str(phase0))
+   part = part.replace('phase1',str(phase1))
+   part = part.replace('amplitude',str(amplitude))
+   part = part.replace('offset',str(offset))
+   return part
+
+def coscale_xy_z(part,x0,y0,z0,z1,angle0,angle1,amplitude,offset):
+   phase0 = math.pi*angle0/180.
+   phase1 = math.pi*angle1/180.
+   part = part.replace('X','((x0) + (X-(x0))/((offset) + (amplitude)*math.cos((phase0) + ((phase1)-(phase0))*(Z-(z0))/((z1)-(z0)))))')
+   part = part.replace('Y','((y0) + (Y-(y0))/((offset) + (amplitude)*math.cos((phase0) + ((phase1)-(phase0))*(Z-(z0))/((z1)-(z0)))))')
+   part = part.replace('x0',str(x0))
+   part = part.replace('y0',str(y0))
+   part = part.replace('z0',str(z0))
+   part = part.replace('z1',str(z1))
+   part = part.replace('phase0',str(phase0))
+   part = part.replace('phase1',str(phase1))
+   part = part.replace('amplitude',str(amplitude))
+   part = part.replace('offset',str(offset))
+   return part
+
+def taper_x_y(part,x0,y0,y1,s0,s1):
+   part = part.replace('X','((x0) + (X-(x0))*((y1)-(y0))/((s1)*(Y-(y0)) + (s0)*((y1)-Y)))')
+   part = part.replace('x0',str(x0))
+   part = part.replace('y0',str(y0))
+   part = part.replace('y1',str(y1))
+   part = part.replace('s0',str(s0))
+   part = part.replace('s1',str(s1))
+   return part
+
+def taper_x_z(part,x0,z0,z1,s0,s1):
+   part = part.replace('X','((x0) + (X-(x0))*((z1)-(z0))/((s1)*(Z-(z0)) + (s0)*((z1)-Z)))')
+   part = part.replace('x0',str(x0))
+   part = part.replace('z0',str(z0))
+   part = part.replace('z1',str(z1))
+   part = part.replace('s0',str(s0))
+   part = part.replace('s1',str(s1))
+   return part
+
+def taper_xy_z(part,x0,y0,z0,z1,s0,s1):
+   part = part.replace('X','((x0) + (X-(x0))*((z1)-(z0))/((s1)*(Z-(z0)) + (s0)*((z1)-Z)))')
+   part = part.replace('Y','((y0) + (Y-(y0))*((z1)-(z0))/((s1)*(Z-(z0)) + (s0)*((z1)-Z)))')
+   part = part.replace('x0',str(x0))
+   part = part.replace('y0',str(y0))
+   part = part.replace('z0',str(z0))
+   part = part.replace('z1',str(z1))
+   part = part.replace('s0',str(s0))
+   part = part.replace('s1',str(s1))
+   return part
+
+def shear_x_y(part,y0,y1,dx0,dx1):
+   part = part.replace('X','(X - (dx0) - ((dx1)-(dx0))*(Y-(y0))/((y1)-(y0)))')
+   part = part.replace('y0',str(y0))
+   part = part.replace('y1',str(y1))
+   part = part.replace('dx0',str(dx0))
+   part = part.replace('dx1',str(dx1))
+   return part
+
+def shear_x_z(part,z0,z1,dx0,dx1):
+   part = part.replace('X','(X - (dx0) - ((dx1)-(dx0))*(Z-(z0))/((z1)-(z0)))')
+   part = part.replace('z0',str(z0))
+   part = part.replace('z1',str(z1))
+   part = part.replace('dx0',str(dx0))
+   part = part.replace('dx1',str(dx1))
+   return part
+
+def coshear_x_z(part,z0,z1,angle0,angle1,amplitude,offset):
+   phase0 = math.pi*angle0/180.
+   phase1 = math.pi*angle1/180.
+   part = part.replace('X','(X - (offset) - (amplitude)*math.cos((phase0) + ((phase1)-(phase0))*(Z-(z0))/((z1)-(z0))))')
+   part = part.replace('z0',str(z0))
+   part = part.replace('z1',str(z1))
+   part = part.replace('phase0',str(phase0))
+   part = part.replace('phase1',str(phase1))
+   part = part.replace('amplitude',str(amplitude))
+   part = part.replace('offset',str(offset))
+   return part
+
+############################################################
+# text classes and definitions
+############################################################
+
+class text:
+   #
+   # text class
+   #
+   def __init__(self,text,x,y,z=0,line='',height='',width='',space='',align='CC',color=White,angle=0):
+      #
+      # parameters
+      #
+      if (line == ''):
+         line = 1
+      if (height == ''):
+         height = 6*line
+      if (width == ''):
+         width = 4*line
+      if (space == ''):
+         space = line/2.0
+      self.width = 0
+      self.height = 0
+      self.text = text
+      #
+      # construct shape dictionary
+      #
+      shapes = {}
+      shape = triangle(0,0,width/2.0,height,width,0)
+      cutout = triangle(0,-2.5*line,width/2.0,height-2.5*line,width,-2.5*line)
+      cutout = subtract(cutout,rectangle(0,width,height/4-line/2,height/4+line/2))
+      shape = subtract(shape,cutout)
+      shapes['A'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = subtract(shape,circle(width/2,width/2,width/4))
+      shape = add(shape,rectangle(width-line,width,0,height/3))
+      shapes['a'] = shape
+      shape = rectangle(0,width-height/4,0,height)
+      shape = add(shape,circle(width-height/4,height/4,height/4))
+      shape = add(shape,circle(width-height/4,3*height/4,height/4))
+      w = height/2-1.5*line
+      shape = subtract(shape,rectangle(line,line+w/1.5,height/2+line/2,height-line))
+      shape = subtract(shape,circle(line+w/1.5,height/2+line/2+w/2,w/2))
+      shape = subtract(shape,rectangle(line,line+w/1.5,line,height/2-line/2))
+      shape = subtract(shape,circle(line+w/1.5,height/2-line/2-w/2,w/2))
+      shapes['B'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = subtract(shape,circle(width/2,width/2,width/4))
+      shape = add(shape,rectangle(0,line,0,height))
+      shapes['b'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = add(shape,circle(width/2,height-width/2,width/2))
+      shape = add(shape,rectangle(0,width,line+w/2,height-line-w/2))
+      w = width-2*line
+      shape = subtract(shape,circle(width/2,line+w/2,w/2))
+      shape = subtract(shape,circle(width/2,height-line-w/2,w/2))
+      shape = subtract(shape,rectangle(line,width,line+w/2,height-line-w/2))
+      shapes['C'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = subtract(shape,circle(width/2,width/2,width/4))
+      shape = subtract(shape,rectangle(width/2,width,width/2-line/1.5,width/2+line/1.5))
+      shapes['c'] = shape
+      shape = circle(line,width-line,width-line)
+      shape = subtract(shape,circle(line,width-line,width-2*line))
+      shape = subtract(shape,rectangle(-width,line,0,height))
+      shape = scale_y(shape,0,height/(2*(width-line)))
+      shape = add(shape,rectangle(0,line,0,height))
+      shapes['D'] = shape
+      shape = rectangle(width-line,width,0,height)
+      shape = add(shape,circle(width/2,width/2,width/2))
+      shape = subtract(shape,circle(width/2,width/2,width/2-line))
+      shapes['d'] = shape
+      shape = rectangle(0,line,0,height)
+      shape = add(shape,rectangle(0,width,height-line,height))
+      shape = add(shape,rectangle(0,2*width/3,height/2-line/2,height/2+line/2))
+      shape = add(shape,rectangle(0,width,0,line))      
+      shapes['E'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = subtract(shape,circle(width/2,width/2,width/2-line))
+      shape = subtract(shape,triangle(width,0,width/2,width/2-line/2,width,width/2-line/2))
+      shape = add(shape,rectangle(0,width,width/2-line/2,width/2+line/2))
+      shapes['e'] = shape
+      shape = rectangle(0,line,0,height)
+      shape = add(shape,rectangle(0,width,height-line,height))
+      shape = add(shape,rectangle(0,2*width/3,height/2-line/2,height/2+line/2))
+      shapes['F'] = shape
+      shape = circle(width-line/2,height-width/2,width/2)
+      shape = subtract(shape,circle(width-line/2,height-width/2,width/2-line))
+      shape = subtract(shape,rectangle(0,width-line/2,0,height-width/2))
+      shape = subtract(shape,rectangle(width-line/2,2*width,0,height))
+      shape = add(shape,rectangle(width/2-line/2,width/2+line/2,0,height-width/2))
+      shape = add(shape,rectangle(width/5,4*width/5,height/2-line/2,height/2+line/2))
+      shapes['f'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = add(shape,circle(width/2,height-width/2,width/2))
+      shape = add(shape,rectangle(0,width,line+w/2,height-line-w/2))
+      w = width-2*line
+      shape = subtract(shape,circle(width/2,line+w/2,w/2))
+      shape = subtract(shape,circle(width/2,height-line-w/2,w/2))
+      shape = subtract(shape,rectangle(line,width,line+w/2,height-line-w/2))
+      shape = add(shape,rectangle(width/2,width,line+w/2,2*line+w/2))
+      shapes['G'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = subtract(shape,circle(width/2,width/2,width/2-line))
+      w = height/3-width/2
+      shape = add(shape,rectangle(width-line,width,w,width))
+      shape = add(shape,subtract(subtract(circle(width/2,w,width/2),circle(width/2,w,width/2-line)),rectangle(0,width,w,height)))
+      shapes['g'] = shape
+      shape = rectangle(0,line,0,height)
+      shape = add(shape,rectangle(width-line,width,0,height))
+      shape = add(shape,rectangle(0,width,height/2-line/2,height/2+line/2))
+      shapes['H'] = shape
+      w = width/2
+      shape = circle(width/2,w,width/2)
+      shape = subtract(shape,circle(width/2,w,width/2-line))
+      shape = subtract(shape,rectangle(0,width,0,w))
+      shape = add(shape,rectangle(0,line,0,height))
+      shape = add(shape,rectangle(width-line,width,0,w))
+      shapes['h'] = shape
+      shape = rectangle(width/2-line/2,width/2+line/2,0,height)
+      shape = add(shape,rectangle(width/5,4*width/5,0,line))
+      shape = add(shape,rectangle(width/5,4*width/5,height-line,height))
+      shapes['I'] = shape
+      shape = rectangle(width/2-line/2,width/2+line/2,0,height/2)
+      shape = add(shape,circle(width/2,3*height/4,.6*line))
+      shapes['i'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = subtract(shape,circle(width/2,width/2,width/2-line))
+      shape = subtract(shape,rectangle(0,width,width/2,height))
+      shape = add(shape,rectangle(width-line,width,width/2,height))
+      shapes['J'] = shape
+      w = height/3-width/2
+      shape = rectangle(width/2-line/2,width/2+line/2,w,height/2)
+      shape = add(shape,subtract(subtract(subtract(circle(width/4-line/2,w,width/2),circle(width/4-line/2,w,width/2-line)),rectangle(0,width,w,height)),rectangle(-width,width/4-line/2,-height/3,height)))
+      shape = add(shape,circle(width/2,3*height/4,.6*line))
+      shapes['j'] = shape
+      shape = rectangle(0,width,0,height)
+      shape = subtract(shape,triangle(line,height,width-1.1*line,height,line,height/2+.5*line))
+      shape = subtract(shape,triangle(width,0,line+0.8*line,height/2,width,height))
+      shape = subtract(shape,triangle(line,0,line,height/2-.5*line,width-1.1*line,0))
+      shapes['K'] = shape
+      shape = rectangle(0,width,0,height)
+      shape = subtract(shape,rectangle(line,width,2*height/3,height))
+      shape = subtract(shape,triangle(line,2*height/3,width-1.3*line,2*height/3,line,height/3+.5*line))
+      shape = subtract(shape,triangle(width,0,line+0.8*line,height/3,width,2*height/3))
+      shape = subtract(shape,triangle(line,0,line,height/3-0.5*line,width-1.3*line,0))
+      shapes['k'] = shape
+      shape = rectangle(0,line,0,height)
+      shape = add(shape,rectangle(0,width,0,line))
+      shapes['L'] = shape
+      shape = rectangle(width/2-line/2,width/2+line/2,0,height)
+      shapes['l'] = shape
+      shape = rectangle(0,width,0,height)
+      shape = subtract(shape,triangle(line,0,line,height-3*line,width/2-line/3,0))
+      shape = subtract(shape,triangle(line,height,width-line,height,width/2,1.5*line))
+      shape = subtract(shape,triangle(width/2+line/3,0,width-line,height-3*line,width-line,0))
+      shapes['M'] = shape
+      w = width/2
+      l = 1.3*line
+      shape = circle(width/2,w,width/2)
+      shape = subtract(shape,circle(width/2,w,width/2-l))
+      shape = subtract(shape,rectangle(0,width,0,w))
+      shape = add(shape,rectangle(width-l,width,0,w))
+      shape = add(shape,move(shape,width-l,0))
+      shape = add(shape,rectangle(0,l,0,width))
+      shape = scale_x(shape,0,width/(2*width-l))
+      shapes['m'] = shape
+      shape = rectangle(0,width,0,height)
+      shape = subtract(shape,triangle(line,height+1.5*line,width-line,height+1.5*line,width-line,1.5*line))
+      shape = subtract(shape,triangle(line,-1.5*line,line,height-1.5*line,width-line,-1.5*line))
+      shapes['N'] = shape
+      w = width/2
+      shape = circle(width/2,w,width/2)
+      shape = subtract(shape,circle(width/2,w,width/2-line))
+      shape = subtract(shape,rectangle(0,width,0,w))
+      shape = add(shape,rectangle(0,line,0,width))
+      shape = add(shape,rectangle(width-line,width,0,w))
+      shapes['n'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = add(shape,circle(width/2,height-width/2,width/2))
+      shape = add(shape,rectangle(0,width,line+w/2,height-line-w/2))
+      w = width-2*line
+      shape = subtract(shape,circle(width/2,line+w/2,w/2))
+      shape = subtract(shape,circle(width/2,height-line-w/2,w/2))
+      shape = subtract(shape,rectangle(line,width-line,line+w/2,height-line-w/2))
+      shapes['O'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = subtract(shape,circle(width/2,width/2,width/2-line))
+      shapes['o'] = shape
+      shape = rectangle(0,line,0,height)
+      w = 2*height/3
+      shape = add(shape,circle(width-w/2,height-w/2,w/2))
+      shape = add(shape,rectangle(0,width-w/2,height-w,height))
+      shape = subtract(shape,circle(width-w/2,height-w/2,w/2-line))
+      shape = subtract(shape,rectangle(line,width-w/2,height-w+line,height-line))
+      shapes['P'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = subtract(shape,circle(width/2,width/2,width/4))
+      shape = add(shape,rectangle(0,line,-height/3,width))
+      shapes['p'] = shape
+      shape = subtract(circle(width/2,width/2,width/2),circle(width/2,width/2,width/2-.9*line))
+      shape = scale_y(shape,0,height/width)
+      shape = add(shape,move(rotate(rectangle(-line/2,line/2,-width/4,width/4),30),3*width/4,width/4))
+      shapes['Q'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = subtract(shape,circle(width/2,width/2,width/2-line))
+      shape = add(shape,rectangle(width-line,width,-height/3,width))
+      shapes['q'] = shape
+      shape = rectangle(0,line,0,height)
+      w = 2*height/3
+      shape = add(shape,circle(width-w/2,height-w/2,w/2))
+      shape = add(shape,rectangle(0,width-w/2,height-w,height))
+      shape = subtract(shape,circle(width-w/2,height-w/2,w/2-line))
+      shape = subtract(shape,rectangle(line,width-w/2,height-w+line,height-line))
+      leg = triangle(line,0,line,height,width,0)
+      leg = subtract(leg,triangle(line,-2.0*line,line,height-2.0*line,width,-2.0*line))
+      leg = subtract(leg,rectangle(0,width,height/3,height))
+      shape = add(shape,leg)
+      shapes['R'] = shape
+      shape = circle(width,0,width)
+      shape = subtract(shape,circle(width,0,width-line))
+      shape = subtract(shape,rectangle(.8*width,2*width,-height,height))
+      shape = subtract(shape,rectangle(0,2*width,-height,0))
+      shape = add(shape,rectangle(0,line,0,width))
+      shapes['r'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = subtract(shape,circle(width/2,width/2,width/2-line))
+      shape = subtract(shape,rectangle(0,width/2,width/2,width))
+      shape = add(shape,move(reflect_y(reflect_x(shape,width),width),0,width-line))
+      shape = scale_y(shape,0,height/(2*width-line))
+      shapes['S'] = shape
+      w = width/3
+      shape = circle(w,w,w)
+      shape = subtract(shape,circle(w,w,w-.9*line))
+      shape = subtract(shape,rectangle(0,w,w,2*w))
+      shape = add(shape,move(reflect_y(reflect_x(shape,2*w),2*w),0,2*w-.9*line))
+      shape = scale_y(shape,0,(2*height/3)/(4*w-.9*line))
+      shape = move(shape,(width/2)-w,0)
+      shapes['s'] = shape
+      shape = rectangle(width/2-line/2,width/2+line/2,0,height)
+      shape = add(shape,rectangle(0,width,height-line,height))
+      shapes['T'] = shape
+      shape = circle(0,3*width/8,3*width/8)
+      shape = subtract(shape,circle(0,3*width/8,3*width/8-line))
+      shape = subtract(shape,rectangle(-width,width,3*width/8,height))
+      shape = subtract(shape,rectangle(0,width,-height,height))
+      shape = move(shape,width/2-line/2+3*width/8,0)
+      shape = add(shape,rectangle(width/2-line/2,width/2+line/2,width/4,3*height/4))
+      shape = add(shape,rectangle(width/5,4*width/5,height/2-line/2,height/2+line/2))
+      shapes['t'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = subtract(shape,circle(width/2,width/2,width/2-line))
+      shape = subtract(shape,rectangle(0,width,width/2,height))
+      shape = add(shape,rectangle(0,line,width/2,height))
+      shape = add(shape,rectangle(width-line,width,width/2,height))
+      shapes['U'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = subtract(shape,circle(width/2,width/2,width/2-line))
+      shape = subtract(shape,rectangle(0,width,width/2,height))
+      shape = add(shape,rectangle(0,line,width/2,2*height/3))
+      shape = add(shape,rectangle(width-line,width,0,2*height/3))
+      shapes['u'] = shape
+      shape = triangle(0,height,width,height,width/2,0)
+      shape = subtract(shape,triangle(0,height+3*line,width,height+3*line,width/2,3*line))
+      shapes['V'] = shape
+      w = 2*height/3.0
+      shape = triangle(0,w,width,w,width/2,0)
+      shape = subtract(shape,triangle(0,w+2*line,width,w+2*line,width/2,2*line))
+      shapes['v'] = shape
+      shape = triangle(0,height,width,height,width/2,0)
+      shape = add(shape,move(shape,.6*width,0))
+      cutout = triangle(0,height+4*line,width,height+4*line,width/2,4*line)
+      cutout = add(cutout,move(cutout,.6*width,0))
+      shape = subtract(shape,cutout)
+      shape = scale_x(shape,0,1/1.6)
+      shapes['W'] = shape
+      shape = scale_y(shapes['W'],0,width/height)
+      shapes['w'] = shape
+      shape = rectangle(0,width,0,height)
+      shape = subtract(shape,triangle(0,0,0,height,width/2-.7*line,height/2))
+      shape = subtract(shape,triangle(width,0,width/2+.7*line,height/2,width,height))
+      shape = subtract(shape,triangle(1.1*line,height,width-1.1*line,height,width/2,height/2+line))
+      shape = subtract(shape,triangle(1.1*line,0,width/2,height/2-line,width-1.1*line,0))
+      shapes['X'] = shape
+      w = 2*height/3.0
+      shape = rectangle(0,width,0,w)
+      shape = subtract(shape,triangle(0,0,0,w,width/2-.75*line,w/2))
+      shape = subtract(shape,triangle(width,0,width/2+.75*line,w/2,width,w))
+      shape = subtract(shape,triangle(1.25*line,0,width/2,w/2-.75*line,width-1.25*line,0))
+      shape = subtract(shape,triangle(1.25*line,w,width-1.25*line,w,width/2,w/2+.75*line))
+      shapes['x'] = shape
+      w = height/2
+      shape = rectangle(0,width,w,height)
+      shape = subtract(shape,triangle(0,w,0,height,width/2-line/2,w))
+      shape = subtract(shape,triangle(width/2+line/2,w,width,height,width,w))
+      shape = subtract(shape,triangle(1.1*line,height,width-1.1*line,height,width/2,w+1.1*line))
+      shape = add(shape,rectangle(width/2-line/2,width/2+line/2,0,w))
+      shapes['Y'] = shape
+      shape = rectangle(0,width,-height/3,width)
+      shape = subtract(shape,triangle(0,-height/3,0,width,width/2-.9*line,0))
+      shape = subtract(shape,triangle(1.1*line,width,width-1.1*line,width,width/2-.2*line,1.6*line))
+      shape = subtract(shape,triangle(1.2*line,-height/3,width,width,width,-height/3))
+      shapes['y'] = shape
+      shape = rectangle(0,width,0,height)
+      shape = subtract(shape,triangle(0,line,0,height-line,width-1.4*line,height-line))
+      shape = subtract(shape,triangle(1.4*line,line,width,height-line,width,line))
+      shapes['Z'] = shape
+      w = 2*height/3
+      shape = rectangle(0,width,0,w)
+      shape = subtract(shape,triangle(0,line,0,w-line,width-1.6*line,w-line))
+      shape = subtract(shape,triangle(width,line,1.6*line,line,width,w-line))
+      shapes['z'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = subtract(shape,circle(width/2,width/2,width/2-.9*line))
+      shape = scale_y(shape,0,height/width)
+      shapes['0'] = shape
+      shape = rectangle(width/2-line/2,width/2+line/2,0,height)
+      w = width/2-line/2
+      cutout = circle(0,height,w)
+      shape = add(shape,rectangle(0,width/2,height-w-line,height))
+      shape = subtract(shape,cutout)
+      shape = move(shape,(width/2+line/2)/4,0)
+      shapes['1'] = shape
+      shape = circle(width/2,height-width/2,width/2)
+      shape = subtract(shape,circle(width/2,height-width/2,width/2-line))
+      shape = subtract(shape,rectangle(0,width/2,0,height-width/2))
+      shape = add(shape,rectangle(0,width,0,height-width/2))
+      shape = subtract(shape,triangle(0,line,0,height-width/2,width-line,height-width/2))
+      shape = subtract(shape,triangle(1.5*line,line,width,height-width/2-.5*line,width,line))
+      shapes['2'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = subtract(shape,circle(width/2,width/2,width/2-line))
+      shape = scale_y(shape,0,(height/2+line/2)/width)
+      shape = add(shape,move(shape,0,height/2-line/2))
+      shape = subtract(shape,rectangle(0,width/2,height/4,3*height/4))
+      shapes['3'] = shape
+      shape = rectangle(width-line,width,0,height)
+      shape = add(shape,triangle(0,height/3,width-line,height,width-line,height/3))
+      shape = subtract(shape,triangle(1.75*line,height/3+line,width-line,height-1.5*line,width-line,height/3+line))
+      shapes['4'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = subtract(shape,circle(width/2,width/2,width/2-line))
+      shape = subtract(shape,rectangle(0,width/2,width/2,width))
+      shape = add(shape,rectangle(0,width/2,width-line,width))
+      shape = add(shape,rectangle(0,line,width-line,height))
+      shape = add(shape,rectangle(0,width,height-line,height))
+      shapes['5'] = shape
+      shape = circle(width/2,height-width/2,width/2)
+      shape = subtract(shape,circle(width/2,height-width/2,width/2-line))
+      shape = subtract(shape,rectangle(0,width,0,height-width/2))
+      shape = subtract(shape,triangle(width,height,width,height/2,width/2,height/2))
+      shape = add(shape,circle(width/2,width/2,width/2))
+      shape = subtract(shape,circle(width/2,width/2,width/2-line))
+      shape = add(shape,rectangle(0,line,width/2,height-width/2))
+      shapes['6'] = shape
+      shape = rectangle(0,width,0,height)
+      shape = subtract(shape,triangle(0,0,0,height-line,width-line,height-line))
+      shape = subtract(shape,triangle(line,0,width,height-line,width,0))
+      shapes['7'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = subtract(shape,circle(width/2,width/2,width/2-line))
+      shape = scale_y(shape,0,(height/2+line/2)/width)
+      shape = add(shape,move(shape,0,height/2-line/2))
+      shapes['8'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = subtract(shape,circle(width/2,width/2,width/2-line))
+      shape = subtract(shape,rectangle(0,width,width/2,height))
+      shape = subtract(shape,triangle(0,0,0,height/2,width/2,height/2))
+      shape = add(shape,circle(width/2,height-width/2,width/2))
+      shape = subtract(shape,circle(width/2,height-width/2,width/2-line))
+      shape = add(shape,rectangle(width-line,width,width/2,height-width/2))
+      shapes['9'] = shape
+      w = width/2
+      shape = circle(w,w,w)
+      shape = subtract(shape,circle(w,w,w-line))
+      shape = subtract(shape,rectangle(w,width,0,height))
+      shape = scale_y(shape,0,height/width)
+      shape = move(shape,w/2,0)
+      shapes['('] = shape
+      shape = reflect_x(shape,width)
+      shapes[')'] = shape
+      shapes[' '] = false
+      shape = rectangle(width/2-width/3,width/2+width/3,height/2-line/2,height/2+line/2)
+      shape = add(shape,rectangle(width/2-line/2,width/2+line/2,height/2-width/3,height/2+width/3))
+      shapes['+'] = shape
+      shape = rectangle(width/2-width/3,width/2+width/3,height/2-line/2,height/2+line/2)
+      shapes['-'] = shape
+      shape = circle(width/2,line,.75*line)
+      shapes['.'] = shape
+      shape = rectangle(0,width,0,height)
+      d = .8*line
+      shape = subtract(shape,triangle(d,0,width,height-d,width,0))
+      shape = subtract(shape,triangle(0,d,0,height,width-d,height))
+      shapes['/'] = shape
+      #
+      # to be done
+      #
+      shapes['*'] = shape
+      shapes['~'] = shape
+      shapes['!'] = shape
+      shapes['@'] = shape
+      shapes['#'] = shape
+      shapes['$'] = shape
+      shapes['%'] = shape
+      shapes['^'] = shape
+      shapes['&'] = shape
+      shapes['&'] = shape
+      shapes['_'] = shape
+      shapes['='] = shape
+      shapes['['] = shape
+      shapes['{'] = shape
+      shapes[']'] = shape
+      shapes['}'] = shape
+      shapes[';'] = shape
+      shapes[':'] = shape
+      shapes["'"] = shape
+      shapes['"'] = shape
+      shapes[','] = shape
+      shapes['<'] = shape
+      shapes['>'] = shape
+      shapes['?'] = shape
+      #
+      # add a line to text shape
+      #
+      def addline(lineshape):
+         #
+         # LR align
+         #
+         if (align[0] == 'C'):
+            lineshape = move(lineshape,-self.width/2.0,0)
+         elif (align[0] == 'R'):
+            lineshape = move(lineshape,-self.width,0)
+         #
+         # add
+         #
+         self.shape = add(self.shape,lineshape)
+      #
+      # loop over chars
+      #
+      dx = 0
+      dy = -height
+      self.width = -space
+      self.height = height
+      lineshape = false
+      self.shape = false
+      count = 0
+      for chr in text:
+         if (chr == '\n'):
+            count += 1
+            addline(lineshape)
+            dx = 0
+            dy -= 1.5*self.height/(1+(count-1)*1.5)
+            self.width = -space
+            self.height += 1.5*self.height
+            lineshape = false
+         else:
+            lineshape = add(lineshape,move(shapes[chr],dx,dy))
+            self.width += space + width
+            dx += width + space
+      addline(lineshape)
+      #
+      # UD align
+      #
+      if (align[1] == 'C'):
+         self.shape = move(self.shape,0,self.height/2.0)
+      elif (align[1] == 'B'):
+         self.shape = move(self.shape,0,self.height)
+      #
+      # rotate
+      #
+      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)
+      elif (angle != 0):
+         self.shape = rotate(self.shape,angle)
+      #
+      # translate
+      #
+      self.shape = move(self.shape,x,y)
+      #
+      # color
+      #
+      self.shape = '('+str(color)+'*(('+self.shape+')!=0))'
+
+############################################################
+# PCB classes and definitions
+############################################################
+
+class PCB:
+   def __init__(self,x0,y0,width,height,mask):
+      self.board = false
+      self.labels = false
+      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
+      self.cutout = 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 point:
+   def __init__(self,x,y,z=0):
+      self.x = x
+      self.y = y
+      self.z = z
+
+class part:
+   class text:
+      def __init__(self,x,y,z=0,text='',line=0.006,angle=0):
+         self.x = x
+         self.y = y
+         self.z = z
+         self.text = text
+         self.line = line 
+         self.angle = angle
+   def add(self,pcb,x,y,z=0,angle=0,line=0.007):
+      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)
+      elif (angle != 0):
+         self.shape = rotate(self.shape,angle)
+      self.shape = translate(self.shape,x,y,z)
+      if hasattr(self,'holes'):
+         if (angle == 90):
+            self.holes = rotate_90(self.holes)
+         elif (angle == 180):
+            self.holes = rotate_180(self.holes)
+         elif ((angle == 270) | (angle == -90)):
+            self.holes = rotate_270(self.holes)
+         elif (angle != 0):
+            self.holes = rotate(self.holes,angle)
+         self.holes = translate(self.holes,x,y,z)
+      if hasattr(self,'cutout'):
+         if (angle == 90):
+            self.cutout = rotate_90(self.cutout)
+         elif (angle == 180):
+            self.cutout = rotate_180(self.cutout)
+         elif ((angle == 270) | (angle == -90)):
+            self.cutout = rotate_270(self.cutout)
+         elif (angle != 0):
+            self.cutout = rotate(self.cutout,angle)
+         self.cutout = translate(self.cutout,x,y,z)
+      deg_angle = angle
+      angle = math.pi*angle/180
+      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
+         self.pad[i].x = x + xnew
+         self.pad[i].y = y + ynew
+         self.pad[i].z += z
+      pcb.labels = add(pcb.labels,text(self.value,x,y,z,line=line,color=Green).shape)
+      for i in range(len(self.labels)):
+         xnew = math.cos(angle)*self.labels[i].x - math.sin(angle)*self.labels[i].y
+         ynew = math.sin(angle)*self.labels[i].x + math.cos(angle)*self.labels[i].y
+         self.labels[i].x = x + xnew
+         self.labels[i].y = y + ynew
+         self.labels[i].z += z
+         if ((-90 < deg_angle) & (deg_angle <= 90)):
+            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).shape)
+         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)
+      if hasattr(self,'holes'):
+         pcb.holes = add(pcb.holes,self.holes)
+      if hasattr(self,'cutout'):
+         pcb.interior = subtract(pcb.interior,self.cutout)
+         pcb.exterior = add(pcb.exterior,self.cutout)
+      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))
+   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
+      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 wirer(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
+############################################################
+
+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))
+
+class SJ(part):
+   #
+   # solder jumper
+   #
+   def __init__(self,value=''):
+      pad_SJ = cube(-.02,.02,-.03,.03,0,0)
+      self.value = value
+      self.labels = []
+      self.pad = [point(0,0,0)]
+      self.shape = translate(pad_SJ,-.029,0,0)
+      self.pad.append(point(-.029,0,0))
+      self.shape = add(self.shape,translate(pad_SJ,.029,0,0))
+      self.pad.append(point(.029,0,0))
+
+############################################################
+# discretes
+############################################################
+
+
+class ST4EB(part):
+   #
+   # Nidec Copal ST4ETB103 trimpot
+   #
+   def __init__(self,value=''):
+      pad1 = cube(-.032,.032,-.039,.039,0,0)
+      pad2 = cube(-.039,.039,-.039,.039,0,0)
+      self.value = value
+      self.labels = []
+      self.pad = [point(0,0,0)]
+      self.shape = translate(pad1,-.046,-.118,0)
+      self.pad.append(point(-.046,-.118,0))
+      self.shape = add(self.shape,translate(pad1,.046,-.118,0))
+      self.pad.append(point(.046,-.118,0))
+      self.shape = add(self.shape,translate(pad2,0,.118,0))
+      self.pad.append(point(0,.118,0))
+
+class C_FND(part):
+   #
+   # Panasonic FN series, size code D
+   #    100uF: EEE-FN1E101UL
+   #
+   def __init__(self,value=''):
+      pad = cube(-.032,.032,-.06,.06,0,0)
+      self.value = value
+      self.labels = []
+      self.pad = [point(0,0,0)]
+      self.shape = translate(pad,0,.11,0)
+      self.pad.append(point(0,.11,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'+',angle=90))
+      self.shape = add(self.shape,translate(pad,0,-.11,0))
+      self.pad.append(point(0,-.11,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'-',angle=90))
+
+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
+############################################################
+
+class header_2H(part):
+   #
+   # 2x1x0.1 cable header
+   #    Sullins GEC36SBSN-M89	
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_header,0,.05,0)
+      self.pad.append(point(0,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.05,0))
+      self.pad.append(point(0,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'2'))
+
+class header_4H(part):
+   #
+   # 4x1x0.1 cable header
+   #    Sullins GEC36SBSN-M89	
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_header,0,.15,0)
+      self.pad.append(point(0,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.05,0))
+      self.pad.append(point(0,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'2'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.05,0))
+      self.pad.append(point(0,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'3'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-0.15,0))
+      self.pad.append(point(0,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'4'))
+
+class header_NEO_6M(part):
+   #
+   # NEO_6M GPS module
+   #
+   def __init__(self,value=''):
+      pad_header = cylinder(0,0,0,0,.03)
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_header,0,.2,0)
+      self.pad.append(point(0,.2,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PPS'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.1,0))
+      self.pad.append(point(0,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'TXD'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_header,0,0,0))
+      self.pad.append(point(0,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RXD'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.1,0))
+      self.pad.append(point(0,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.2,0))
+      self.pad.append(point(0,-.2,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC'))
+
+class header_MFRC522(part):
+   #
+   # MFCR522 RFID module
+   #
+   def __init__(self,value=''):
+      pad_header = cylinder(0,0,0,0,.03)
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_header,0,.35,0)
+      self.pad.append(point(0,.35,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1SDA'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.25,0))
+      self.pad.append(point(0,.25,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCK'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.15,0))
+      self.pad.append(point(0,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'COPI'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_header,0,0.05,0))
+      self.pad.append(point(0,0.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CIPO'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.05,0))
+      self.pad.append(point(0,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IRQ'))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.15,0))
+      self.pad.append(point(0,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.25,0))
+      self.pad.append(point(0,-.25,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RST'))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.35,0))
+      self.pad.append(point(0,-.35,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'3.3V'))
+
+class header_LSM6DS33_2736(part):
+   #
+   # LSD6DS33 carrier
+   #    Pololu 2736
+   #
+   def __init__(self,value=''):
+      pad_header = cylinder(0,0,0,0,.03)
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_header,0,.4,0)
+      self.pad.append(point(0,.4,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1VDD'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.3,0))
+      self.pad.append(point(0,.3,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VIN'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.2,0))
+      self.pad.append(point(0,.2,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_header,0,0.1,0))
+      self.pad.append(point(0,0.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SDA'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad_header,0,0,0))
+      self.pad.append(point(0,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCL'))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.1,0))
+      self.pad.append(point(0,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SDO'))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.2,0))
+      self.pad.append(point(0,-.2,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CS'))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.3,0))
+      self.pad.append(point(0,-.3,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'INT2'))
+      #
+      # pin 9
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.4,0))
+      self.pad.append(point(0,-.4,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'INT1'))
+
+class header_VL53L1X_3415(part):
+   #
+   # VL53L1X carrier
+   #    Pololu 3415
+   #
+   def __init__(self,value=''):
+      pad_header = cylinder(0,0,0,0,.03)
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_header,0,.3,0)
+      self.pad.append(point(0,.3,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1VDD'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.2,0))
+      self.pad.append(point(0,.2,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VIN'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.1,0))
+      self.pad.append(point(0,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_header,0,0,0))
+      self.pad.append(point(0,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SDA'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.1,0))
+      self.pad.append(point(0,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCL'))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.2,0))
+      self.pad.append(point(0,-.2,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'XSHUT'))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.3,0))
+      self.pad.append(point(0,-.3,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GPIO1'))
+
+class ESP_WROOM_02D(part):
+   #
+   # ESP-WROOM-02D
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      pad = cube(-1/25.4,1/25.4,-.45/25.4,.45/25.4,0,0)
+      width = 17.5/25.4
+      pitch = 1.5/25.4
+      #
+      # pin 1
+      #
+      self.shape = translate(pad,-width/2,4*pitch,0)
+      self.shape = add(self.shape,cylinder(-width/2-.75/25.4,4*pitch,0,0,.45/25.4))
+      self.pad.append(point(-width/2,4*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'3V3'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,3*pitch,0))
+      self.pad.append(point(-width/2,3*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'EN'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,2*pitch,0))
+      self.pad.append(point(-width/2,2*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO14'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,1*pitch,0))
+      self.pad.append(point(-width/2,1*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO12'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,0*pitch,0))
+      self.pad.append(point(-width/2,0*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO13'))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,-1*pitch,0))
+      self.pad.append(point(-width/2,-1*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO15'))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,-2*pitch,0))
+      self.pad.append(point(-width/2,-2*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO2'))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,-3*pitch,0))
+      self.pad.append(point(-width/2,-3*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO0'))
+      #
+      # pin 9
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,-4*pitch,0))
+      self.pad.append(point(-width/2,-4*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 10
+      #
+      self.shape = add(self.shape,translate(pad,width/2,-4*pitch,0))
+      self.pad.append(point(width/2,-4*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO4'))
+      #
+      # pin 11
+      #
+      self.shape = add(self.shape,translate(pad,width/2,-3*pitch,0))
+      self.pad.append(point(width/2,-3*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RXD'))
+      #
+      # pin 12
+      #
+      self.shape = add(self.shape,translate(pad,width/2,-2*pitch,0))
+      self.pad.append(point(width/2,-2*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'TXD'))
+      #
+      # pin 13
+      #
+      self.shape = add(self.shape,translate(pad,width/2,-1*pitch,0))
+      self.pad.append(point(width/2,-1*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 14
+      #
+      self.shape = add(self.shape,translate(pad,width/2,0*pitch,0))
+      self.pad.append(point(width/2,0*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO5'))
+      #
+      # pin 15
+      #
+      self.shape = add(self.shape,translate(pad,width/2,1*pitch,0))
+      self.pad.append(point(width/2,1*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RST'))
+      #
+      # pin 16
+      #
+      self.shape = add(self.shape,translate(pad,width/2,2*pitch,0))
+      self.pad.append(point(width/2,2*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'TOUT'))
+      #
+      # pin 17
+      #
+      self.shape = add(self.shape,translate(pad,width/2,3*pitch,0))
+      self.pad.append(point(width/2,3*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO16'))
+      #
+      # pin 18
+      #
+      self.shape = add(self.shape,translate(pad,width/2,4*pitch,0))
+      self.pad.append(point(width/2,4*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 19
+      #
+      padg = cube(-2/25.4,2/25.4,-2/25.4,2/25.4,0,0)
+      self.shape = add(self.shape,translate(padg,(1.5/2+7.1+2-17.5/2)/25.4,(4*1.5+7.1-20+4.29+2)/25.4,0))
+      self.pad.append(point((1.5/2+7.1+2-17.5/2)/25.4,(4*1.5+7.1-20+4.29+2)/25.4,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+
+class ESP_01(part):
+   #
+   # ESP-01 4x2 vertical
+   #    Sullins NPTC042KFMS-RC	
+   #
+   def __init__(self,value=''):
+      pad_header = cube(-.075/2,.075/2,-.04/2,.04/2,0,0)
+      d = .305/2-.07/2
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_header,d,.15,0)
+      self.shape = add(self.shape,cylinder(d+.061/2,.15,0,0,.039/2))
+      self.pad.append(point(d,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,-d,.15,0))
+      self.pad.append(point(-d,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Tx'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_header,d,.05,0))
+      self.pad.append(point(d,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO2'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_header,-d,.05,0))
+      self.pad.append(point(-d,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'EN'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad_header,d,-.05,0))
+      self.pad.append(point(d,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO0'))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad_header,-d,-.05,0))
+      self.pad.append(point(-d,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RST'))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad_header,d,-.15,0))
+      self.pad.append(point(d,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Rx'))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(pad_header,-d,-.15,0))
+      self.pad.append(point(-d,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC'))
+
+class header_serial_reverse_5V(part):
+   #
+   # serial cable header, reverse for female connector, 5V output
+   #    GCT BG300-06-A-L-A	
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_header,0,-.25,0)
+      self.shape = add(self.shape,cylinder(-.05,-.25,0,0,.025))
+      self.pad.append(point(0,-.25,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.15,0))
+      self.pad.append(point(0,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CTS'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.05,0))
+      self.pad.append(point(0,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'5V'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_header,0,0.05,0))
+      self.pad.append(point(0,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Tx'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.15,0))
+      self.pad.append(point(0,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Rx'))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.25,0))
+      self.pad.append(point(0,.25,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RTS'))
+
+class header_serial_reverse_3V3(part):
+   #
+   # serial cable header, reverse for female connector, 3.3V output
+   #    GCT BG300-06-A-L-A	
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_header,0,-.25,0)
+      self.shape = add(self.shape,cylinder(-.05,-.25,0,0,.025))
+      self.pad.append(point(0,-.25,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.15,0))
+      self.pad.append(point(0,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CTS'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.05,0))
+      self.pad.append(point(0,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'3.3V'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_header,0,0.05,0))
+      self.pad.append(point(0,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Tx'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.15,0))
+      self.pad.append(point(0,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Rx'))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.25,0))
+      self.pad.append(point(0,.25,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RTS'))
+
+class TFT8x1v(part):
+   #
+   # TFT 8x1 vertical
+   #    2x Sullins S5635-ND
+   #
+   def __init__(self,value=''):
+      pad_header = cube(-.079/2,.079/2,-.039/2,.039/2,0,0)
+      d = .209/2-.079/2
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_header,-d,-.35,0)
+      self.pad.append(point(-d,-.35,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1LED'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,d,-.25,0))
+      self.pad.append(point(d,-.25,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCK'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_header,-d,-.15,0))
+      self.pad.append(point(-d,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'MOSI'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_header,d,-.05,0))
+      self.pad.append(point(d,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DC'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad_header,-d,.05,0))
+      self.pad.append(point(-d,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RST'))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad_header,d,.15,0))
+      self.pad.append(point(d,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CS'))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad_header,-d,.25,0))
+      self.pad.append(point(-d,.25,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(pad_header,d,.35,0))
+      self.pad.append(point(d,.35,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC'))
+
+class header_SWD_4_05(part):
+   #
+   # 4-pin header
+   # Sullins GRPB022VWQS-RC 2x2x0.05"
+   #
+   def __init__(self,value=''):
+      pad_header = cube(-.043,.043,-.015,.015,0,0)
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_header,-.072,.025,0)
+      self.shape = add(self.shape,cylinder(-.116,.025,0,0,.015))
+      self.pad.append(point(-.072,.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CLK'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,.072,.025,0))
+      self.pad.append(point(.072,.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DIO'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_header,-.072,-.025,0))
+      self.pad.append(point(-.072,-.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RST'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_header,.072,-.025,0))
+      self.pad.append(point(.072,-.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+
+class header_SWD_4_1(part):
+   #
+   # 4-pin header
+   # FCI 95278-101a04lf Bergstik 2x2x0.1"
+   #
+   pad_header = cube(-.05,.05,-.025,.025,0,0)
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_header,-.107,.05,0)
+      #self.shape = add(self.shape,cylinder(-.157,.05,0,0,.025))
+      self.pad.append(point(-.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CLK'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.05,0))
+      self.pad.append(point(.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DIO'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.05,0))
+      self.pad.append(point(-.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RST'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,-.05,0))
+      self.pad.append(point(.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+
+class header_UPDI(part):
+   #
+   # UPDI header
+   #    Sullins GEC36SBSN-M89	
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: UPDI
+      #
+      self.shape = translate(pad_header,0,-.05,0)
+      self.shape = add(self.shape,cylinder(.05,-.05,0,0,.025))
+      self.pad.append(point(0,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'UPDI'))
+      #
+      # pin 2: GND
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.05,0))
+      self.pad.append(point(0,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+
+class header_UPDI_reverse(part):
+   #
+   # UPDI header, reverse for female connector
+   #    GCT BG300-03-A-L-A	
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: UPDI
+      #
+      self.shape = translate(pad_header,0,.05,0)
+      self.shape = add(self.shape,cylinder(.05,.05,0,0,.025))
+      self.pad.append(point(0,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'UPDI'))
+      #
+      # pin 2: GND
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.05,0))
+      self.pad.append(point(0,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+
+class USB_A_plug(part):
+   #
+   # USB type A PCB plug
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: 5V
+      #
+      self.shape = translate(cube(-.05,.242,-.02,.02,0,0),0,.138,0)
+      self.pad.append(point(0,.138,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'5V'))
+      #
+      # pin 2: D-
+      #
+      self.shape = add(self.shape,translate(cube(-0.05,.202,-.02,.02,0,0),0,.039,0))
+      self.pad.append(point(0,.039,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'D-'))
+      #
+      # pin 3: D+
+      #
+      self.shape = add(self.shape,translate(cube(-.05,.202,-.02,.02,0,0),0,-.039,0))
+      self.pad.append(point(0,-.039,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'D+'))
+      #
+      # pin 4: GND
+      #
+      self.shape = add(self.shape,translate(cube(-.05,.242,-.02,.02,0,0),0,-.138,0))
+      self.pad.append(point(0,-.138,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # plug cutout
+      #
+      self.cutout = cube(-.05,1,.24,10,zb,zt)
+      self.cutout = add(self.cutout,cube(-.05,10,-10,-.24,zb,zt))
+
+class header_SWD(part):
+   #
+   # Serial Wire Debug programming header
+   # Amphenol 20021121-00010T1LF	2x5x0.05
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      d = 0.077
+      w = 0.015
+      h = .047
+      pad = cube(-h,h,-w,w,0,0)
+      #
+      # pin 1: VCC
+      #
+      self.shape = translate(pad,d,-.1,0)
+      self.shape = add(self.shape,cylinder(d+h,-.1,0,0,w))
+      self.pad.append(point(d,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC'))
+      #
+      # pin 2: DIO
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.1,0))
+      self.pad.append(point(-d,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DIO'))
+      #
+      # pin 3: GND
+      #
+      self.shape = add(self.shape,translate(pad,d,-.05,0))
+      self.pad.append(point(d,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 4: CLK
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.05,0))
+      self.pad.append(point(-d,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CLK'))
+      #
+      # pin 5: GND
+      #
+      self.shape = add(self.shape,translate(pad,d,0,0))
+      self.pad.append(point(d,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 6: SWO
+      #
+      self.shape = add(self.shape,translate(pad,-d,0,0))
+      self.pad.append(point(-d,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SWO'))
+      #
+      # pin 7: KEY
+      #
+      self.shape = add(self.shape,translate(pad,d,.05,0))
+      self.pad.append(point(d,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'KEY'))
+      #
+      # pin 8: NC
+      #
+      self.shape = add(self.shape,translate(pad,-d,.05,0))
+      self.pad.append(point(-d,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'NC'))
+      #
+      # pin 9: GND
+      #
+      self.shape = add(self.shape,translate(pad,d,.1,0))
+      self.pad.append(point(d,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 10: nRESET
+      #
+      self.shape = add(self.shape,translate(pad,-d,.1,0))
+      self.pad.append(point(-d,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RST'))
+
+class ESC(part):
+   #
+   # ESC 3x1
+   # Sullins S1013E-36-ND
+   #
+   def __init__(self,value=''):
+      pad_header = cube(-.1,.1,-.05/2,.05/2,0,0)
+      d = .075
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: PWM
+      #
+      self.shape = translate(pad_header,-d,-.1,0)
+      self.pad.append(point(-d,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PWM'))
+      #
+      # pin 2: 5V
+      #
+      self.shape = add(self.shape,translate(pad_header,d,0,0))
+      self.pad.append(point(d,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'5V'))
+      #
+      # pin 3: GND 
+      #
+      self.shape = add(self.shape,translate(pad_header,-d,.1,0))
+      self.pad.append(point(-d,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+
+class I2C4x1h(part):
+   #
+   # I2C 4x1 horizontal female
+   #    GCT BG300-03-A-L-A	
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: SCL
+      #
+      self.shape = translate(pad_header,0,-.15,0)
+      #self.shape = cylinder(.05,.15,0,0,.025)
+      self.pad.append(point(0,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCL'))
+      #
+      # pin 2: SDA
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.05,0))
+      self.pad.append(point(0,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SDA'))
+      #
+      # pin 3: VCC
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.05,0))
+      self.pad.append(point(0,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC'))
+      #
+      # pin 4: GND
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.15,0))
+      self.pad.append(point(0,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+
+class I2C4x1v(part):
+   #
+   # I2C 4x1 vertical
+   #    Sullins S5635-ND
+   #
+   def __init__(self,value=''):
+      pad_header = cube(-.079/2,.079/2,-.039/2,.039/2,0,0)
+      d = .209/2-.079/2
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: VCC
+      #
+      self.shape = translate(pad_header,-d,-.15,0)
+      self.pad.append(point(-d,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1VCC'))
+      #
+      # pin 2: GND
+      #
+      self.shape = add(self.shape,translate(pad_header,d,-.05,0))
+      self.pad.append(point(d,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 3: SCL
+      #
+      self.shape = add(self.shape,translate(pad_header,-d,.05,0))
+      self.pad.append(point(-d,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCL'))
+      #
+      # pin 4: SDA
+      #
+      self.shape = add(self.shape,translate(pad_header,d,.15,0))
+      self.pad.append(point(d,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SDA'))
+
+class I2C4x1i(part):
+   #
+   # I2C 4x1 inline
+   #
+   def __init__(self,value=''):
+      pad_header = cube(-.079/2,.079/2,-.039/2,.039/2,0,0)
+      d = 0
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: VCC
+      #
+      self.shape = translate(pad_header,-d,-.15,0)
+      self.pad.append(point(-d,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1VCC'))
+      #
+      # pin 2: GND
+      #
+      self.shape = add(self.shape,translate(pad_header,d,-.05,0))
+      self.pad.append(point(d,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 3: SCL
+      #
+      self.shape = add(self.shape,translate(pad_header,-d,.05,0))
+      self.pad.append(point(-d,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCL'))
+      #
+      # pin 4: SDA
+      #
+      self.shape = add(self.shape,translate(pad_header,d,.15,0))
+      self.pad.append(point(d,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SDA'))
+
+class RCWL0516(part):
+   #
+   # RCWL-0516 Doppler radar
+   #
+   def __init__(self,value=''):
+      pad_header = cube(-.065,.065,-.025,.025,0,0)
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: 3.3V
+      #
+      self.shape = translate(pad_header,.107,-.2,0)
+      self.shape = add(self.shape,cylinder(.172,-.2,0,0,.025))
+      self.pad.append(point(.107,-.2,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'3.3V'))
+      #
+      # pin 2: GND
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.1,0))
+      self.pad.append(point(-.107,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 3: OUT
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,0,0))
+      self.pad.append(point(.107,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'OUT'))
+      #
+      # pin 4: VIN
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,.1,0))
+      self.pad.append(point(-.107,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VIN'))
+      #
+      # pin 5: CDS
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.2,0))
+      self.pad.append(point(.107,.2,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CDS'))
+
+class microSD(part):
+   #
+   # microSD
+   # Amphenol 114-00841-68
+   # 
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(cube(-.0138,.0138,-.034,.034,0,0),-.177+7*.0433,-.304,0)
+      self.pad.append(point(-.177+7*.0433,-.304,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1NC',angle=90))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(cube(-.0138,.0138,-.034,.034,0,0),-.177+6*.0433,-.304,0))
+      self.pad.append(point(-.177+6*.0433,-.304,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SS',angle=90))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(cube(-.0138,.0138,-.034,.034,0,0),-.177+5*.0433,-.304,0))
+      self.pad.append(point(-.177+5*.0433,-.304,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'MOSI',angle=90))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(cube(-.0138,.0138,-.034,.034,0,0),-.177+4*.0433,-.304,0))
+      self.pad.append(point(-.177+4*.0433,-.304,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC',angle=90))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(cube(-.0138,.0138,-.034,.034,0,0),-.177+3*.0433,-.304,0))
+      self.pad.append(point(-.177+3*.0433,-.304,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCK',angle=90))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(cube(-.0138,.0138,-.034,.034,0,0),-.177+2*.0433,-.304,0))
+      self.pad.append(point(-.177+2*.0433,-.304,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',angle=90))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(cube(-.0138,.0138,-.034,.034,0,0),-.177+1*.0433,-.304,0))
+      self.pad.append(point(-.177+1*.0433,-.304,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'MISO',angle=90))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(cube(-.0138,.0138,-.034,.034,0,0),-.177+0*.0433,-.304,0))
+      self.pad.append(point(-.177+0*.0433,-.304,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'NC',angle=90))
+      #
+      # feet
+      #
+      self.shape = add(self.shape,translate(cube(-.021,.021,-.029,.029,0,0),-.228,-.299,0)) # leave extra space for 1/64 milling
+      self.shape = add(self.shape,translate(cube(-.029,.029,-.029,.029,0,0),.222,-.299,0))
+      self.shape = add(self.shape,translate(cube(-.015,.015,-.029,.025,0,0),-.232,0,0)) # leave extra space for 1/64 milling
+      self.shape = add(self.shape,translate(cube(-.015,.015,-.029,.029,0,0),-.232+.47,.025,0))
+      self.shape = add(self.shape,translate(cube(-.028,.028,-.019,.019,0,0),-.221,.059,0))
+      self.shape = add(self.shape,translate(cube(-.019,.019,-.030,.030,0,0),.222,.121,0))
+
+pad_USB_trace = cube(-.0075,.0075,-.04,.04,0,0)
+pad_USB_feet = cube(-.049,.049,-.043,.043,0,0)
+
+class USB_mini_B(part):
+   #
+   # USB mini B
+   # Hirose UX60-MB-5ST
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_USB_trace,.063,.36,0)
+      self.pad.append(point(.063,.36,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_USB_trace,.0315,.36,0))
+      self.pad.append(point(.0315,.36,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,''))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_USB_trace,0,.36,0))
+      self.pad.append(point(0,.36,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'+'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_USB_trace,-.0315,.36,0))
+      self.pad.append(point(-.0315,.36,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'-'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad_USB_trace,-.063,.36,0))
+      self.pad.append(point(-.063,.36,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V'))
+      #
+      # feet
+      #
+      self.shape = add(self.shape,translate(pad_USB_feet,.165,.33,0))
+      self.shape = add(self.shape,translate(pad_USB_feet,-.165,.33,0))
+      self.shape = add(self.shape,translate(pad_USB_feet,.165,.12,0))
+      self.shape = add(self.shape,translate(pad_USB_feet,-.165,.12,0))
+
+pad_header = cube(-.05,.05,-.025,.025,0,0)
+
+class header_4(part):
+   #
+   # 4-pin header
+   # fci 95278-101a04lf bergstik 2x2x0.1"
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_header,-.107,.05,0)
+      self.shape = add(self.shape,cylinder(-.157,.05,0,0,.025))
+      self.pad.append(point(-.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.05,0))
+      self.pad.append(point(.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'2'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.05,0))
+      self.pad.append(point(-.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'3'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,-.05,0))
+      self.pad.append(point(.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'4'))
+
+class header_signal(part):
+   #
+   # signal header
+   # FCI 95278-101A04LF Bergstik 2x2x0.1"
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: Gnd
+      #
+      self.shape = translate(pad_header,.107,-.05,0)
+      self.shape = add(self.shape,cylinder(.157,-.05,0,0,.025))
+      self.pad.append(point(.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.05,0))
+      self.pad.append(point(-.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,''))
+      #
+      # pin 3: signal
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.05,0))
+      self.pad.append(point(.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'signal'))
+      #
+      # pin 4:
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,.05,0))
+      self.pad.append(point(-.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,''))
+
+
+class header_power(part):
+   #
+   # power header
+   # FCI 95278-101A04LF Bergstik 2x2x0.1"
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: Gnd
+      #
+      self.shape = translate(pad_header,.107,-.05,0)
+      self.shape = add(self.shape,cylinder(.157,-.05,0,0,.025))
+      self.pad.append(point(.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.05,0))
+      self.pad.append(point(-.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,''))
+      #
+      # pin 3: V
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.05,0))
+      self.pad.append(point(.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V'))
+      #
+      # pin 4:
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,.05,0))
+      self.pad.append(point(-.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,''))
+
+class header_i0(part):
+   #
+   # i0 header
+   # FCI 95278-101A04LF Bergstik 2x2x0.1"
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: Gnd
+      #
+      self.shape = translate(pad_header,.107,-.05,0)
+      self.shape = add(self.shape,cylinder(.157,-.05,0,0,.025))
+      self.pad.append(point(.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 2: data
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.05,0))
+      self.pad.append(point(-.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'data'))
+      #
+      # pin 3: V
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.05,0))
+      self.pad.append(point(.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V'))
+      #
+      # pin 4:
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,.05,0))
+      self.pad.append(point(-.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,''))
+
+class header_serial(part):
+   #
+   # serial comm header
+   # FCI 95278-101A04LF Bergstik 2x2x0.1"
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: Gnd
+      #
+      self.shape = translate(pad_header,.107,-.05,0)
+      self.shape = add(self.shape,cylinder(.157,-.05,0,0,.025))
+      self.pad.append(point(.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 2:DTR
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.05,0))
+      self.pad.append(point(-.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DTR'))
+      #
+      # pin 3: Tx
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.05,0))
+      self.pad.append(point(.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Tx'))
+      #
+      # pin 4: Rx
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,.05,0))
+      self.pad.append(point(-.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Rx'))
+
+class header_bus(part):
+   #
+   # bus header
+   # FCI 95278-101A04LF Bergstik 2x2x0.1"
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: Gnd
+      #
+      self.shape = translate(pad_header,.107,-.05,0)
+      self.shape = add(self.shape,cylinder(.157,-.05,0,0,.025))
+      self.pad.append(point(.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 2: Tx
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.05,0))
+      self.pad.append(point(-.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Tx'))
+      #
+      # pin 3: V
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.05,0))
+      self.pad.append(point(.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V'))
+      #
+      # pin 4: Rx
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,.05,0))
+      self.pad.append(point(-.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Rx'))
+
+class header_I2C(part):
+   #
+   # I2C header
+   # FCI 95278-101A04LF Bergstik 2x2x0.1"
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: SCL
+      #
+      self.shape = translate(pad_header,.107,-.05,0)
+      self.shape = add(self.shape,cylinder(.157,-.05,0,0,.025))
+      self.pad.append(point(.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCL'))
+      #
+      # pin 2: G
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.05,0))
+      self.pad.append(point(-.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G'))
+      #
+      # pin 3: SDA
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.05,0))
+      self.pad.append(point(.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SDA'))
+      #
+      # pin 4: V
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,.05,0))
+      self.pad.append(point(-.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V'))
+
+class header_APA(part):
+   #
+   # APA header
+   # FCI 95278-101A04LF Bergstik 2x2x0.1"
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: Gnd
+      #
+      self.shape = translate(pad_header,.107,-.05,0)
+      self.shape = add(self.shape,cylinder(.157,-.05,0,0,.025))
+      self.pad.append(point(.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 2: in
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.05,0))
+      self.pad.append(point(-.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'in'))
+      #
+      # pin 3: V
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.05,0))
+      self.pad.append(point(.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V'))
+      #
+      # pin 4: out
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,.05,0))
+      self.pad.append(point(-.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'out'))
+
+class header_6(part):
+   #
+   # 6-pin header
+   # FCI 95278-101A06LF Bergstik 2x3x0.1"
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_header,.107,-.1,0)
+      self.shape = add(self.shape,cylinder(.157,-.1,0,0,.025))
+      self.pad.append(point(.107,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,''))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.1,0))
+      self.pad.append(point(-.107,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,''))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,0,0))
+      self.pad.append(point(.107,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,''))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,0,0))
+      self.pad.append(point(-.107,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,''))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.1,0))
+      self.pad.append(point(.107,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,''))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,.1,0))
+      self.pad.append(point(-.107,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,''))
+
+class header_ATP(part):
+   #
+   # Asynchronous Token Protocol header
+   # FCI 95278-101A06LF Bergstik 2x3x0.1"
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_header,.107,-.1,0)
+      self.shape = add(self.shape,cylinder(.157,-.1,0,0,.025))
+      self.pad.append(point(.107,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'BI'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.1,0))
+      self.pad.append(point(-.107,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'TI'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,0,0))
+      self.pad.append(point(.107,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,0,0))
+      self.pad.append(point(-.107,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.1,0))
+      self.pad.append(point(.107,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'TO'))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,.1,0))
+      self.pad.append(point(-.107,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'BO'))
+
+class header_PDI(part):
+   #
+   # in-circuit PDI programming header
+   # FCI 95278-101A06LF Bergstik 2x3x0.1"
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: Data
+      #
+      self.shape = translate(pad_header,.107,-.1,0)
+      self.shape = add(self.shape,cylinder(.157,-.1,0,0,.025))
+      self.pad.append(point(.107,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DAT'))
+      #
+      # pin 2: VCC
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.1,0))
+      self.pad.append(point(-.107,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC'))
+      #
+      # pin 3: NC 
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,0,0))
+      self.pad.append(point(.107,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'NC'))
+      #
+      # pin 4: NC
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,0,0))
+      self.pad.append(point(-.107,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'NC'))
+      #
+      # pin 5: Clock
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.1,0))
+      self.pad.append(point(.107,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CLK'))
+      #
+      # pin 6: GND
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,.1,0))
+      self.pad.append(point(-.107,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+
+class header_ISP(part):
+   #
+   # in-circuit ISP programming header
+   # FCI 95278-101A06LF Bergstik 2x3x0.1"
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: MISO
+      #
+      self.shape = translate(pad_header,.107,-.1,0)
+      self.shape = add(self.shape,cylinder(.157,-.1,0,0,.025))
+      self.pad.append(point(.107,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'MISO'))
+      #
+      # pin 2: V
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.1,0))
+      self.pad.append(point(-.107,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V'))
+      #
+      # pin 3: SCK
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,0,0))
+      self.pad.append(point(.107,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCK'))
+      #
+      # pin 4: MOSI
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,0,0))
+      self.pad.append(point(-.107,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'MOSI'))
+      #
+      # pin 5: RST
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.1,0))
+      self.pad.append(point(.107,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RST'))
+      #
+      # pin 6: GND
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,.1,0))
+      self.pad.append(point(-.107,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+
+class header_nRF24L01(part):
+   #
+   # nRF24L01 module header
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1:
+      #
+      self.shape = translate(pad_header,.107,-.15,0)
+      self.shape = add(self.shape,cylinder(.157,-.15,0,0,.025))
+      self.pad.append(point(.107,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 2:
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.15,0))
+      self.pad.append(point(-.107,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC'))
+      #
+      # pin 3:
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,-.05,0))
+      self.pad.append(point(.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CE'))
+      #
+      # pin 4:
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.05,0))
+      self.pad.append(point(-.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CS'))
+      #
+      # pin 5:
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.05,0))
+      self.pad.append(point(.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCK'))
+      #
+      # pin 6:
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,.05,0))
+      self.pad.append(point(-.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'MOSI'))
+      #
+      # pin 7:
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.15,0))
+      self.pad.append(point(.107,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'MISO'))
+      #
+      # pin 8:
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,.15,0))
+      self.pad.append(point(-.107,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IRQ'))
+
+class header_servo(part):
+   #
+   # servo motor header
+   # FCI 95278-101A06LF Bergstik 2x3x0.1"
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: ground
+      #
+      self.shape = translate(pad_header,.107,-.1,0)
+      self.shape = add(self.shape,cylinder(.157,-.1,0,0,.025))
+      self.pad.append(point(.107,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G/blk'))
+      #
+      # pin 2: ground
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.1,0))
+      self.pad.append(point(-.107,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G/blk'))
+      #
+      # pin 3: power
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,0,0))
+      self.pad.append(point(.107,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V/red'))
+      #
+      # pin 4: power
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,0,0))
+      self.pad.append(point(-.107,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V/red'))
+      #
+      # pin 5: signal 0
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.1,0))
+      self.pad.append(point(.107,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'S0/wht'))
+      #
+      # pin 6: signal 1
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,.1,0))
+      self.pad.append(point(-.107,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'S1/wht'))
+
+class header_unipolar_stepper(part):
+   #
+   # unipolar stepper header
+   # FCI 95278-101A06LF Bergstik 2x3x0.1"
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_header,.107,-.1,0)
+      self.shape = add(self.shape,cylinder(.157,-.1,0,0,.025))
+      self.pad.append(point(.107,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'red'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.1,0))
+      self.pad.append(point(-.107,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'green'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,0,0))
+      self.pad.append(point(.107,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'black'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,0,0))
+      self.pad.append(point(-.107,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'brown'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.1,0))
+      self.pad.append(point(.107,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'orange'))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,.1,0))
+      self.pad.append(point(-.107,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'yellow'))
+
+class header_LCD(part):
+   #
+   # LCD interface header
+   # FCI 95278-101A10LF Bergstik 2x3x0.1"
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1:
+      #
+      self.shape = translate(pad_header,.107,-.2,0)
+      self.shape = add(self.shape,cylinder(.157,-.2,0,0,.025))
+      self.pad.append(point(.107,-.2,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DB7\n14'))
+      #
+      # pin 2:
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.2,0))
+      self.pad.append(point(-.107,-.2,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DB6\n13'))
+      #
+      # pin 3:
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,-.1,0))
+      self.pad.append(point(.107,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DB5\n12'))
+      #
+      # pin 4:
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.1,0))
+      self.pad.append(point(-.107,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DB4\n11'))
+      #
+      # pin 5:
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,0,0))
+      self.pad.append(point(.107,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'E\n6'))
+      #
+      # pin 6:
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,0,0))
+      self.pad.append(point(-.107,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'R/W\n5'))
+      #
+      # pin 7:
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.1,0))
+      self.pad.append(point(.107,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RS\n4'))
+      #
+      # pin 8:
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,.1,0))
+      self.pad.append(point(-.107,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Vee\n3'))
+      #
+      # pin 9:
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.2,0))
+      self.pad.append(point(.107,.2,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Vcc\n2'))
+      #
+      # pin 10:
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,.2,0))
+      self.pad.append(point(-.107,.2,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND\n1'))
+
+class header_serial_reverse(part):
+   #
+   # serial cable header, reverse for female connector
+   #    GCT BG300-06-A-L-A	
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: GND
+      #
+      self.shape = translate(pad_header,0,-.25,0)
+      self.shape = add(self.shape,cylinder(-.05,-.25,0,0,.025))
+      self.pad.append(point(0,-.25,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 2: CTS (brown)
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.15,0))
+      self.pad.append(point(0,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CTS'))
+      #
+      # pin 3: VCC (red)
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.05,0))
+      self.pad.append(point(0,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC'))
+      #
+      # pin 4: Tx (orange)
+      #
+      self.shape = add(self.shape,translate(pad_header,0,0.05,0))
+      self.pad.append(point(0,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Tx'))
+      #
+      # pin 5: Rx (yellow)
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.15,0))
+      self.pad.append(point(0,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Rx'))
+      #
+      # pin 6: RTS (green)
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.25,0))
+      self.pad.append(point(0,.25,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RTS'))
+
+class header_FTDI(part):
+   #
+   # FTDI cable header
+   #    Sullins GEC36SBSN-M89	
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: GND
+      #
+      self.shape = translate(pad_header,0,.25,0)
+      self.shape = add(self.shape,cylinder(-.05,.25,0,0,.025))
+      self.pad.append(point(0,.25,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 2: CTS (brown)
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.15,0))
+      self.pad.append(point(0,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CTS'))
+      #
+      # pin 3: VCC (red)
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.05,0))
+      self.pad.append(point(0,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC'))
+      #
+      # pin 4: Tx (orange)
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-0.05,0))
+      self.pad.append(point(0,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Tx'))
+      #
+      # pin 5: Rx (yellow)
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.15,0))
+      self.pad.append(point(0,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Rx'))
+      #
+      # pin 6: RTS (green)
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.25,0))
+      self.pad.append(point(0,-.25,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RTS'))
+
+class HCSR04(part):
+   #
+   # HC-SR04 sonar header
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: GND
+      #
+      self.shape = translate(pad_header,0,.15,0)
+      self.shape = add(self.shape,cylinder(-.05,.15,0,0,.025))
+      self.pad.append(point(0,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 2: echo
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.05,0))
+      self.pad.append(point(0,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'echo'))
+      #
+      # pin 3: trig
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.05,0))
+      self.pad.append(point(0,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'trig'))
+      #
+      # pin 4: Vcc
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-0.15,0))
+      self.pad.append(point(0,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Vcc'))
+
+class HCSR501(part):
+   #
+   # HC-SR501 motion detector header
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: Vcc
+      #
+      self.shape = translate(pad_header,0,.1,0)
+      self.shape = add(self.shape,cylinder(-.05,.1,0,0,.025))
+      self.pad.append(point(0,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Vcc'))
+      #
+      # pin 2: out
+      #
+      self.shape = add(self.shape,translate(pad_header,0,0,0))
+      self.pad.append(point(0,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'out'))
+      #
+      # pin 3: GND
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.1,0))
+      self.pad.append(point(0,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+
+pad_RN4871_left = cube(-0.5/25.4,1/25.4,-0.7/2/25.4,0.7/2/25.4,0,0)
+pad_RN4871_right = cube(-1/25.4,0.5/25.4,-0.7/2/25.4,0.7/2/25.4,0,0)
+pad_RN4871_bot = cube(-0.7/2/25.4,0.7/2/25.4,-0.5/25.4,1/25.4,0,0)
+
+class RN4871(part):
+   #
+   # RN4871
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      width = 9/25.4
+      height = 7.5/25.4
+      bottom = 1.9/25.4
+      left = 1.5/25.4
+      pitch = 1.2/25.4
+      size = .004
+      #
+      # pin 1:
+      #
+      self.shape = translate(pad_RN4871_left,-width/2.0,-height+bottom+4*pitch,0)
+      self.pad.append(point(-width/2.0,-height+bottom+4*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'BT_RF',line=size))
+      #
+      # pin 2: 
+      #
+      self.shape = add(self.shape,translate(pad_RN4871_left,-width/2.0,-height+bottom+3*pitch,0))
+      self.pad.append(point(-width/2.0,-height+bottom+3*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=size))
+      #
+      # pin 3: 
+      #
+      self.shape = add(self.shape,translate(pad_RN4871_left,-width/2.0,-height+bottom+2*pitch,0))
+      self.pad.append(point(-width/2.0,-height+bottom+2*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'P1_2',line=size))
+      #
+      # pin 4: 
+      #
+      self.shape = add(self.shape,translate(pad_RN4871_left,-width/2.0,-height+bottom+1*pitch,0))
+      self.pad.append(point(-width/2.0,-height+bottom+1*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'P1_3',line=size))
+      #
+      # pin 5: 
+      #
+      self.shape = add(self.shape,translate(pad_RN4871_left,-width/2.0,-height+bottom+0*pitch,0))
+      self.pad.append(point(-width/2.0,-height+bottom+0*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'P1_7',line=size))
+      #
+      # pin 6: 
+      #
+      self.shape = add(self.shape,translate(pad_RN4871_bot,-width/2.0+left+0*pitch,-height,0))
+      self.pad.append(point(-width/2.0+left+0*pitch,-height,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'P1_6',line=size,angle=90))
+      #
+      # pin 7: 
+      #
+      self.shape = add(self.shape,translate(pad_RN4871_bot,-width/2.0+left+1*pitch,-height,0))
+      self.pad.append(point(-width/2.0+left+1*pitch,-height,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RX',line=size,angle=90))
+      #
+      # pin 8: 
+      #
+      self.shape = add(self.shape,translate(pad_RN4871_bot,-width/2.0+left+2*pitch,-height,0))
+      self.pad.append(point(-width/2.0+left+2*pitch,-height,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'TX',line=size,angle=90))
+      #
+      # pin 9: 
+      #
+      self.shape = add(self.shape,translate(pad_RN4871_bot,-width/2.0+left+3*pitch,-height,0))
+      self.pad.append(point(-width/2.0+left+3*pitch,-height,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'P3_6',line=size,angle=90))
+      #
+      # pin 10: 
+      #
+      self.shape = add(self.shape,translate(pad_RN4871_bot,-width/2.0+left+4*pitch,-height,0))
+      self.pad.append(point(-width/2.0+left+4*pitch,-height,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RST_N',line=size,angle=90))
+      #
+      # pin 11: 
+      #
+      self.shape = add(self.shape,translate(pad_RN4871_bot,-width/2.0+left+5*pitch,-height,0))
+      self.pad.append(point(-width/2.0+left+5*pitch,-height,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'P0_0',line=size,angle=90))
+      #
+      # pin 12:
+      #
+      self.shape = add(self.shape,translate(pad_RN4871_right,width/2.0,-height+bottom+0*pitch,0))
+      self.pad.append(point(width/2.0,-height+bottom+0*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'P0_2',line=size))
+      #
+      # pin 13:
+      #
+      self.shape = add(self.shape,translate(pad_RN4871_right,width/2.0,-height+bottom+1*pitch,0))
+      self.pad.append(point(width/2.0,-height+bottom+1*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=size))
+      #
+      # pin 14:
+      #
+      self.shape = add(self.shape,translate(pad_RN4871_right,width/2.0,-height+bottom+2*pitch,0))
+      self.pad.append(point(width/2.0,-height+bottom+2*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VBAT',line=size))
+      #
+      # pin 15:
+      #
+      self.shape = add(self.shape,translate(pad_RN4871_right,width/2.0,-height+bottom+3*pitch,0))
+      self.pad.append(point(width/2.0,-height+bottom+3*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'P2_7',line=size))
+      #
+      # pin 16:
+      #
+      self.shape = add(self.shape,translate(pad_RN4871_right,width/2.0,-height+bottom+4*pitch,0))
+      self.pad.append(point(width/2.0,-height+bottom+4*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'P2_0',line=size))
+
+pad_HM11 = cube(-.047,.047,-.0177,.0177,0,0)
+
+class HM11(part):
+   #
+   # HM-11
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      height = 18.5/25.4 
+      width = 13.5/25.4
+      pitch = 1.5/25.4
+      bottom = 1/25.4
+      offset = 0
+      size = .004
+      #
+      # pin 1:
+      #
+      self.shape = translate(pad_HM11,-width/2.0+offset,-height/2.0+bottom+7*pitch,0)
+      self.pad.append(point(-width/2.0+offset,-height/2.0+bottom+7*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RTS',line=size))
+      #
+      # pin 2: 
+      #
+      self.shape = add(self.shape,translate(pad_HM11,-width/2.0+offset,-height/2.0+bottom+6*pitch,0))
+      self.pad.append(point(-width/2.0+offset,-height/2.0+bottom+6*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'TX',line=size))
+      #
+      # pin 3: 
+      #
+      self.shape = add(self.shape,translate(pad_HM11,-width/2.0+offset,-height/2.0+bottom+5*pitch,0))
+      self.pad.append(point(-width/2.0+offset,-height/2.0+bottom+5*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CTS',line=size))
+      #
+      # pin 4: 
+      #
+      self.shape = add(self.shape,translate(pad_HM11,-width/2.0+offset,-height/2.0+bottom+4*pitch,0))
+      self.pad.append(point(-width/2.0+offset,-height/2.0+bottom+4*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RX',line=size))
+      #
+      # pin 5: 
+      #
+      self.shape = add(self.shape,translate(pad_HM11,-width/2.0+offset,-height/2.0+bottom+3*pitch,0))
+      self.pad.append(point(-width/2.0+offset,-height/2.0+bottom+3*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'NC',line=size))
+      #
+      # pin 6: 
+      #
+      self.shape = add(self.shape,translate(pad_HM11,-width/2.0+offset,-height/2.0+bottom+2*pitch,0))
+      self.pad.append(point(-width/2.0+offset,-height/2.0+bottom+2*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'NC',line=size))
+      #
+      # pin 7: 
+      #
+      self.shape = add(self.shape,translate(pad_HM11,-width/2.0+offset,-height/2.0+bottom+1*pitch,0))
+      self.pad.append(point(-width/2.0+offset,-height/2.0+bottom+1*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'NC',line=size))
+      #
+      # pin 8:
+      #
+      self.shape = add(self.shape,translate(pad_HM11,-width/2.0+offset,-height/2.0+bottom+0*pitch,0))
+      self.pad.append(point(-width/2.0+offset,-height/2.0+bottom+0*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'NC',line=size))
+      #
+      # pin 9:
+      #
+      self.shape = add(self.shape,translate(pad_HM11,width/2.0-offset,-height/2.0+bottom+0*pitch,0))
+      self.pad.append(point(width/2.0-offset,-height/2.0+bottom+0*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC',line=size))
+      #
+      # pin 10:
+      #
+      self.shape = add(self.shape,translate(pad_HM11,width/2.0-offset,-height/2.0+bottom+1*pitch,0))
+      self.pad.append(point(width/2.0-offset,-height/2.0+bottom+1*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'NC',line=size))
+      #
+      # pin 11:
+      #
+      self.shape = add(self.shape,translate(pad_HM11,width/2.0-offset,-height/2.0+bottom+2*pitch,0))
+      self.pad.append(point(width/2.0-offset,-height/2.0+bottom+2*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RST',line=size))
+      #
+      # pin 12:
+      #
+      self.shape = add(self.shape,translate(pad_HM11,width/2.0-offset,-height/2.0+bottom+3*pitch,0))
+      self.pad.append(point(width/2.0-offset,-height/2.0+bottom+3*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=size))
+      #
+      # pin 13:
+      #
+      self.shape = add(self.shape,translate(pad_HM11,width/2.0-offset,-height/2.0+bottom+4*pitch,0))
+      self.pad.append(point(width/2.0-offset,-height/2.0+bottom+4*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO3',line=size))
+      #
+      # pin 14:
+      #
+      self.shape = add(self.shape,translate(pad_HM11,width/2.0-offset,-height/2.0+bottom+5*pitch,0))
+      self.pad.append(point(width/2.0-offset,-height/2.0+bottom+5*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO2',line=size))
+      #
+      # pin 15:
+      #
+      self.shape = add(self.shape,translate(pad_HM11,width/2.0-offset,-height/2.0+bottom+6*pitch,0))
+      self.pad.append(point(width/2.0-offset,-height/2.0+bottom+6*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO1',line=size))
+      #
+      # pin 16:
+      #
+      self.shape = add(self.shape,translate(pad_HM11,width/2.0-offset,-height/2.0+bottom+7*pitch,0))
+      self.pad.append(point(width/2.0-offset,-height/2.0+bottom+7*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO0',line=size))
+
+class ESP32_WROOM(part):
+   #
+   # ESP32-WROOM
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      pad = cube(-1/25.4,1/25.4,-.4/25.4,.4/25.4,0,0)
+      padb = cube(-.4/25.4,.4/25.4,-1/25.4,1/25.4,0,0)
+      width = 17/25.4
+      height = 25.5/25.4
+      pitch = 1.27/25.4
+      #
+      # pin 1
+      #
+      self.shape = translate(pad,-width/2,6*pitch,0)
+      self.pad.append(point(-width/2,6*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,5*pitch,0))
+      self.pad.append(point(-width/2,5*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'3V3'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,4*pitch,0))
+      self.pad.append(point(-width/2,4*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'EN'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,3*pitch,0))
+      self.pad.append(point(-width/2,3*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VP'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,2*pitch,0))
+      self.pad.append(point(-width/2,2*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VN'))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,1*pitch,0))
+      self.pad.append(point(-width/2,1*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO34'))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,0*pitch,0))
+      self.pad.append(point(-width/2,0*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO35'))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,-1*pitch,0))
+      self.pad.append(point(-width/2,-1*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO32'))
+      #
+      # pin 9
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,-2*pitch,0))
+      self.pad.append(point(-width/2,-2*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO33'))
+      #
+      # pin 10
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,-3*pitch,0))
+      self.pad.append(point(-width/2,-3*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO25'))
+      #
+      # pin 11
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,-4*pitch,0))
+      self.pad.append(point(-width/2,-4*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO26'))
+      #
+      # pin 12
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,-5*pitch,0))
+      self.pad.append(point(-width/2,-5*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO27'))
+      #
+      # pin 13
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,-6*pitch,0))
+      self.pad.append(point(-width/2,-6*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO14'))
+      #
+      # pin 14
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,-7*pitch,0))
+      self.pad.append(point(-width/2,-7*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO12'))
+      #
+      # pin 15
+      #
+      self.shape = add(self.shape,translate(padb,-4.5*pitch,-7*pitch-1/25.4,0))
+      self.pad.append(point(-4.5*pitch,-7*pitch-1/25.4,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',angle=90))
+      #
+      # pin 16
+      #
+      self.shape = add(self.shape,translate(padb,-3.5*pitch,-7*pitch-1/25.4,0))
+      self.pad.append(point(-3.5*pitch,-7*pitch-1/25.4,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO13',angle=90))
+      #
+      # pin 17
+      #
+      self.shape = add(self.shape,translate(padb,-2.5*pitch,-7*pitch-1/25.4,0))
+      self.pad.append(point(-2.5*pitch,-7*pitch-1/25.4,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SHD',angle=90))
+      #
+      # pin 18
+      #
+      self.shape = add(self.shape,translate(padb,-1.5*pitch,-7*pitch-1/25.4,0))
+      self.pad.append(point(-1.5*pitch,-7*pitch-1/25.4,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SWP',angle=90))
+      #
+      # pin 19
+      #
+      self.shape = add(self.shape,translate(padb,-0.5*pitch,-7*pitch-1/25.4,0))
+      self.pad.append(point(-0.5*pitch,-7*pitch-1/25.4,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCS',angle=90))
+      #
+      # pin 20
+      #
+      self.shape = add(self.shape,translate(padb,0.5*pitch,-7*pitch-1/25.4,0))
+      self.pad.append(point(0.5*pitch,-7*pitch-1/25.4,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCK',angle=90))
+      #
+      # pin 21
+      #
+      self.shape = add(self.shape,translate(padb,1.5*pitch,-7*pitch-1/25.4,0))
+      self.pad.append(point(1.5*pitch,-7*pitch-1/25.4,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SDO',angle=90))
+      #
+      # pin 22
+      #
+      self.shape = add(self.shape,translate(padb,2.5*pitch,-7*pitch-1/25.4,0))
+      self.pad.append(point(2.5*pitch,-7*pitch-1/25.4,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SDI',angle=90))
+      #
+      # pin 23
+      #
+      self.shape = add(self.shape,translate(padb,3.5*pitch,-7*pitch-1/25.4,0))
+      self.pad.append(point(3.5*pitch,-7*pitch-1/25.4,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO15',angle=90))
+      #
+      # pin 24
+      #
+      self.shape = add(self.shape,translate(padb,4.5*pitch,-7*pitch-1/25.4,0))
+      self.pad.append(point(4.5*pitch,-7*pitch-1/25.4,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO2',angle=90))
+      #
+      # pin 25
+      #
+      self.shape = add(self.shape,translate(pad,width/2,-7*pitch,0))
+      self.pad.append(point(width/2,-7*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO0'))
+      #
+      # pin 26
+      #
+      self.shape = add(self.shape,translate(pad,width/2,-6*pitch,0))
+      self.pad.append(point(width/2,-6*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO4'))
+      #
+      # pin 27
+      #
+      self.shape = add(self.shape,translate(pad,width/2,-5*pitch,0))
+      self.pad.append(point(width/2,-5*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO16'))
+      #
+      # pin 28
+      #
+      self.shape = add(self.shape,translate(pad,width/2,-4*pitch,0))
+      self.pad.append(point(width/2,-4*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO17'))
+      #
+      # pin 29
+      #
+      self.shape = add(self.shape,translate(pad,width/2,-3*pitch,0))
+      self.pad.append(point(width/2,-3*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO5'))
+      #
+      # pin 30
+      #
+      self.shape = add(self.shape,translate(pad,width/2,-2*pitch,0))
+      self.pad.append(point(width/2,-2*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO18'))
+      #
+      # pin 31
+      #
+      self.shape = add(self.shape,translate(pad,width/2,-1*pitch,0))
+      self.pad.append(point(width/2,-1*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO19'))
+      #
+      # pin 32
+      #
+      self.shape = add(self.shape,translate(pad,width/2,0*pitch,0))
+      self.pad.append(point(width/2,0*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'NC'))
+      #
+      # pin 33
+      #
+      self.shape = add(self.shape,translate(pad,width/2,1*pitch,0))
+      self.pad.append(point(width/2,1*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO21'))
+      #
+      # pin 34
+      #
+      self.shape = add(self.shape,translate(pad,width/2,2*pitch,0))
+      self.pad.append(point(width/2,2*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RX0'))
+      #
+      # pin 35
+      #
+      self.shape = add(self.shape,translate(pad,width/2,3*pitch,0))
+      self.pad.append(point(width/2,3*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'TX0'))
+      #
+      # pin 36
+      #
+      self.shape = add(self.shape,translate(pad,width/2,4*pitch,0))
+      self.pad.append(point(width/2,4*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO22'))
+      #
+      # pin 37
+      #
+      self.shape = add(self.shape,translate(pad,width/2,5*pitch,0))
+      self.pad.append(point(width/2,5*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO23'))
+      #
+      # pin 38
+      #
+      self.shape = add(self.shape,translate(pad,width/2,6*pitch,0))
+      self.pad.append(point(width/2,6*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+
+class ESP32_CAM(part):
+   #
+   # ESP32-CAM
+   # Sullins S5635-ND
+   #
+   def __init__(self,value=''):
+      pad_header = cube(-.079/2,.079/2,-.039/2,.039/2,0,0)
+      d = .209/2-.079/2
+      w = 0.9
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_header,+d-w/2,.35,0)
+      self.pad.append(point(+d-w/2,.35,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'+5V'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,-d-w/2,.25,0))
+      self.pad.append(point(-d-w/2,.25,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_header,+d-w/2,.15,0))
+      self.pad.append(point(+d-w/2,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO12'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_header,-d-w/2,.05,0))
+      self.pad.append(point(-d-w/2,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO13'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad_header,+d-w/2,-.05,0))
+      self.pad.append(point(+d-w/2,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO15'))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad_header,-d-w/2,-.15,0))
+      self.pad.append(point(-d-w/2,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO14'))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad_header,+d-w/2,-.25,0))
+      self.pad.append(point(+d-w/2,-.25,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO2'))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(pad_header,-d-w/2,-.35,0))
+      self.pad.append(point(-d-w/2,-.35,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO4'))
+      #
+      # pin 9
+      #
+      self.shape = add(self.shape,translate(pad_header,-d+w/2,-.35,0))
+      self.pad.append(point(-d+w/2,-.35,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 10
+      #
+      self.shape = add(self.shape,translate(pad_header,+d+w/2,-.25,0))
+      self.pad.append(point(+d+w/2,-.25,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'U0T'))
+      #
+      # pin 11
+      #
+      self.shape = add(self.shape,translate(pad_header,-d+w/2,-.15,0))
+      self.pad.append(point(-d+w/2,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'U0R'))
+      #
+      # pin 12
+      #
+      self.shape = add(self.shape,translate(pad_header,+d+w/2,-.05,0))
+      self.pad.append(point(+d+w/2,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC'))
+      #
+      # pin 13
+      #
+      self.shape = add(self.shape,translate(pad_header,-d+w/2,.05,0))
+      self.pad.append(point(-d+w/2,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 14
+      #
+      self.shape = add(self.shape,translate(pad_header,+d+w/2,.15,0))
+      self.pad.append(point(+d+w/2,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO0'))
+      #
+      # pin 15
+      #
+      self.shape = add(self.shape,translate(pad_header,-d+w/2,.25,0))
+      self.pad.append(point(-d+w/2,.25,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO16'))
+      #
+      # pin 16
+      #
+      self.shape = add(self.shape,translate(pad_header,+d+w/2,.35,0))
+      self.pad.append(point(+d+w/2,.35,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'3V3'))
+
+
+class ESP8266_12E(part):
+   #
+   # ESP8266 12E
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      height = 24/25.4 
+      width = 16/25.4
+      pitch = 2/25.4
+      bottom = 1.8/25.4
+      left = 3/25.4
+      offset = .4/25.4 - .01
+      size = .004
+      pad_ESP8266 = cube(-.0493,.0493,-.0197,.0197,0,0)
+      pad_ESP8266_bot = cube(-.0197,.0197,-.0415,.0415,0,0)
+      #
+      # pin 1:
+      #
+      self.shape = translate(pad_ESP8266,-width/2.0+offset,-height/2.0+bottom+7*pitch,0)
+      self.pad.append(point(-width/2.0+offset,-height/2.0+bottom+7*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RST',line=size))
+      #
+      # pin 2: 
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266,-width/2.0+offset,-height/2.0+bottom+6*pitch,0))
+      self.pad.append(point(-width/2.0+offset,-height/2.0+bottom+6*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'ADC',line=size))
+      #
+      # pin 3: 
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266,-width/2.0+offset,-height/2.0+bottom+5*pitch,0))
+      self.pad.append(point(-width/2.0+offset,-height/2.0+bottom+5*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'EN',line=size))
+      #
+      # pin 4: 
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266,-width/2.0+offset,-height/2.0+bottom+4*pitch,0))
+      self.pad.append(point(-width/2.0+offset,-height/2.0+bottom+4*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GPIO16',line=size))
+      #
+      # pin 5: 
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266,-width/2.0+offset,-height/2.0+bottom+3*pitch,0))
+      self.pad.append(point(-width/2.0+offset,-height/2.0+bottom+3*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GPIO14',line=size))
+      #
+      # pin 6: 
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266,-width/2.0+offset,-height/2.0+bottom+2*pitch,0))
+      self.pad.append(point(-width/2.0+offset,-height/2.0+bottom+2*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GPIO12',line=size))
+      #
+      # pin 7: 
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266,-width/2.0+offset,-height/2.0+bottom+1*pitch,0))
+      self.pad.append(point(-width/2.0+offset,-height/2.0+bottom+1*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GPIO13',line=size))
+      #
+      # pin 8: 
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266,-width/2.0+offset,-height/2.0+bottom+0*pitch,0))
+      self.pad.append(point(-width/2.0+offset,-height/2.0+bottom+0*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VDD',line=size))
+      #
+      # pin 9: 
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266_bot,-width/2.0+left+0*pitch,-height/2.0+offset,0))
+      self.pad.append(point(-width/2.0+left+0*pitch,-height/2.0+offset,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CS',line=size,angle=90))
+      #
+      # pin 10: 
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266_bot,-width/2.0+left+1*pitch,-height/2.0+offset,0))
+      self.pad.append(point(-width/2.0+left+1*pitch,-height/2.0+offset,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'MISO',line=size,angle=90))
+      #
+      # pin 11: 
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266_bot,-width/2.0+left+2*pitch,-height/2.0+offset,0))
+      self.pad.append(point(-width/2.0+left+2*pitch,-height/2.0+offset,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GPIO9',line=size,angle=90))
+      #
+      # pin 12: 
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266_bot,-width/2.0+left+3*pitch,-height/2.0+offset,0))
+      self.pad.append(point(-width/2.0+left+3*pitch,-height/2.0+offset,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GPIO10',line=size,angle=90))
+      #
+      # pin 13: 
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266_bot,-width/2.0+left+4*pitch,-height/2.0+offset,0))
+      self.pad.append(point(-width/2.0+left+4*pitch,-height/2.0+offset,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'MOSI',line=size,angle=90))
+      #
+      # pin 14: 
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266_bot,-width/2.0+left+5*pitch,-height/2.0+offset,0))
+      self.pad.append(point(-width/2.0+left+5*pitch,-height/2.0+offset,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCLK',line=size,angle=90))
+      #
+      # pin 15:
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266,width/2.0-offset,-height/2.0+bottom+0*pitch,0))
+      self.pad.append(point(width/2.0-offset,-height/2.0+bottom+0*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=size))
+      #
+      # pin 16:
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266,width/2.0-offset,-height/2.0+bottom+1*pitch,0))
+      self.pad.append(point(width/2.0-offset,-height/2.0+bottom+1*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GPIO15',line=size))
+      #
+      # pin 17:
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266,width/2.0-offset,-height/2.0+bottom+2*pitch,0))
+      self.pad.append(point(width/2.0-offset,-height/2.0+bottom+2*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GPIO2',line=size))
+      #
+      # pin 18:
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266,width/2.0-offset,-height/2.0+bottom+3*pitch,0))
+      self.pad.append(point(width/2.0-offset,-height/2.0+bottom+3*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GPIO0',line=size))
+      #
+      # pin 19:
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266,width/2.0-offset,-height/2.0+bottom+4*pitch,0))
+      self.pad.append(point(width/2.0-offset,-height/2.0+bottom+4*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GPIO4',line=size))
+      #
+      # pin 20:
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266,width/2.0-offset,-height/2.0+bottom+5*pitch,0))
+      self.pad.append(point(width/2.0-offset,-height/2.0+bottom+5*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GPIO5',line=size))
+      #
+      # pin 21:
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266,width/2.0-offset,-height/2.0+bottom+6*pitch,0))
+      self.pad.append(point(width/2.0-offset,-height/2.0+bottom+6*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RXD',line=size))
+      #
+      # pin 22:
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266,width/2.0-offset,-height/2.0+bottom+7*pitch,0))
+      self.pad.append(point(width/2.0-offset,-height/2.0+bottom+7*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'TXD',line=size))
+
+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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_MTA,.025,.1,0))
+      self.pad.append(point(.025,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'2'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1\nGND'))
+      #
+      # pin 2: Vcc
+      #
+      self.shape = add(self.shape,translate(pad_MTA,.025,.1,0))
+      self.pad.append(point(.025,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Vcc'))
+      #
+      # 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_3(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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1'))
+      #
+      # pin 2: power 
+      #
+      self.shape = add(self.shape,translate(pad_MTA,-.05,.1,0))
+      self.pad.append(point(-.05,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'2'))
+      #
+      # pin 3: data
+      #
+      self.shape = add(self.shape,translate(pad_MTA,0,-.1,0))
+      self.pad.append(point(0,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'3'))
+      #
+      # 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_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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1\nGND'))
+      #
+      # pin 2: power 
+      #
+      self.shape = add(self.shape,translate(pad_MTA,-.05,.1,0))
+      self.pad.append(point(-.05,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V'))
+      #
+      # pin 3: data
+      #
+      self.shape = add(self.shape,translate(pad_MTA,0,-.1,0))
+      self.pad.append(point(0,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'data'))
+      #
+      # 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_4(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
+      #
+      self.shape = translate(pad_MTA,-.075,-.1,0)
+      self.pad.append(point(-.075,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_MTA,.025,-.1,0))
+      self.pad.append(point(.025,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'2'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_MTA,.075,.1,0))
+      self.pad.append(point(.075,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'3'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_MTA,-.025,.1,0))
+      self.pad.append(point(-.025,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'4'))
+      #
+      # 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_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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1'))
+      #
+      # pin 2: Tx
+      #
+      self.shape = add(self.shape,translate(pad_MTA,.025,-.1,0))
+      self.pad.append(point(.025,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Tx'))
+      #
+      # pin 3: Rx
+      #
+      self.shape = add(self.shape,translate(pad_MTA,.075,.1,0))
+      self.pad.append(point(.075,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Rx'))
+      #
+      # pin 4: DTR
+      #
+      self.shape = add(self.shape,translate(pad_MTA,-.025,.1,0))
+      self.pad.append(point(-.025,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DTR'))
+      #
+      # 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_PS2(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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1\nGND'))
+      #
+      # pin 2: data
+      #
+      self.shape = add(self.shape,translate(pad_MTA,.025,-.1,0))
+      self.pad.append(point(.025,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'data'))
+      #
+      # pin 3: clock
+      #
+      self.shape = add(self.shape,translate(pad_MTA,.075,.1,0))
+      self.pad.append(point(.075,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'clock'))
+      #
+      # pin 4: 5V
+      #
+      self.shape = add(self.shape,translate(pad_MTA,-.025,.1,0))
+      self.pad.append(point(-.025,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'5V'))
+      #
+      # 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_5(part):
+   #
+   # AMP 1445121-5
+   # MTA .050 SMT 5-pin vertical
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_MTA,-.1,-.1,0)
+      self.pad.append(point(-.1,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_MTA,0,-.1,0))
+      self.pad.append(point(0,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'2'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_MTA,.1,-.1,0))
+      self.pad.append(point(.1,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'3'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_MTA,.05,.1,0))
+      self.pad.append(point(.05,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'4'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad_MTA,-.05,.1,0))
+      self.pad.append(point(-.05,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'5'))
+      #
+      # 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 MTA_ICP(part):
+   #
+   # AMP 1445121-5
+   # MTA .050 SMT 5-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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'MISO'))
+      #
+      # pin 2: GND
+      #
+      self.shape = add(self.shape,translate(pad_MTA,0,-.1,0))
+      self.pad.append(point(0,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 3: MOSI
+      #
+      self.shape = add(self.shape,translate(pad_MTA,.1,-.1,0))
+      self.pad.append(point(.1,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'MOSI'))
+      #
+      # pin 4: -RESET
+      #
+      self.shape = add(self.shape,translate(pad_MTA,.05,.1,0))
+      self.pad.append(point(.05,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'-RESET'))
+      #
+      # pin 5: SCK
+      #
+      self.shape = add(self.shape,translate(pad_MTA,-.05,.1,0))
+      self.pad.append(point(-.05,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCK'))
+      #
+      # 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))
+
+pad_screw_terminal = cylinder(0,0,0,0,.047)
+hole_screw_terminal = circle(0,0,.025)
+
+class screw_terminal_2(part):
+   #
+   # On Shore ED555/2DS
+   # two position screw terminal
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_screw_terminal,-.069,0,0)
+      self.pad.append(point(-.069,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_screw_terminal,.069,0,0))
+      self.pad.append(point(.069,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'2'))
+      #
+      # holes
+      #
+      self.shape = add(self.shape,translate(hole_screw_terminal,-.069,0,0))
+      self.shape = add(self.shape,translate(hole_screw_terminal,.069,0,0))
+
+class screw_terminal_power(part):
+   #
+   # On Shore ED555/2DS
+   # power screw terminal
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_screw_terminal,-.069,0,0)
+      self.pad.append(point(-.069,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_screw_terminal,.069,0,0))
+      self.pad.append(point(.069,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V'))
+      #
+      # holes
+      #
+      self.shape = add(self.shape,translate(hole_screw_terminal,-.069,0,0))
+      self.shape = add(self.shape,translate(hole_screw_terminal,.069,0,0))
+
+class screw_terminal_i0(part):
+   #
+   # On Shore ED555/3DS
+   # i0 screw terminal
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: Gnd
+      #
+      self.shape = translate(pad_screw_terminal,-.138,0,0)
+      self.pad.append(point(-.138,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Gnd\n1'))
+      #
+      # pin 2: data
+      #
+      self.shape = add(self.shape,pad_screw_terminal)
+      self.pad.append(point(0,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'data'))
+      #
+      # pin 3: V
+      #
+      self.shape = add(self.shape,translate(pad_screw_terminal,.138,0,0))
+      self.pad.append(point(.138,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V'))
+      #
+      # holes
+      #
+      self.shape = add(self.shape,translate(hole_screw_terminal,-.138,0,0))
+      self.shape = add(self.shape,hole_screw_terminal)
+      self.shape = add(self.shape,translate(hole_screw_terminal,.138,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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'P'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'C'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'base'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'tip'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'middle'))
+
+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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Rx'))
+      #
+      # pin 2: Tx
+      #
+      self.shape = add(self.shape,translate(pad_Molex,-.025,.064,0))
+      self.pad.append(point(-.025,.064,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Tx'))
+      #
+      # pin 3: DTR
+      #
+      self.shape = add(self.shape,translate(pad_Molex,.025,.064,0))
+      self.pad.append(point(.025,.064,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DTR'))
+      #
+      # pin 4: GND
+      #
+      self.shape = add(self.shape,translate(pad_Molex,.075,.064,0))
+      self.pad.append(point(.075,.064,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # 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
+############################################################
+
+class slide_switch(part):
+   # 
+   # slide switch
+   # C&K AYZ0102AGRLC
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      pad = cube(-.039/2,.039/2,-.047/2,.047/2,0,0)
+      #
+      # pad 1
+      #
+      self.shape = translate(pad,-.098,.1,0)
+      self.pad.append(point(-.098,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,''))
+      #
+      # pad 2
+      #
+      self.shape = add(self.shape,translate(pad,0,.1,0))
+      self.pad.append(point(0,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,''))
+      #
+      # pad 3
+      #
+      self.shape = add(self.shape,translate(pad,.098,.1,0))
+      self.pad.append(point(.098,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,''))
+      #
+      # holes
+      #
+      self.holes = cylinder(-.118/2,0,zb,zt,.034/2)
+      self.holes = add(self.holes,cylinder(.118/2,0,zb,zt,.034/2))
+
+class button_6mm(part):
+   # 
+   # Omron 6mm pushbutton
+   # B3SN-3112P
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      pad_button_6mm = cube(-.04,.04,-.03,.03,0,0)
+      #
+      # left 1
+      #
+      self.shape = translate(pad_button_6mm,-.125,.08,0)
+      self.pad.append(point(-.125,.08,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'L1'))
+      #
+      # right 1
+      #
+      self.shape = add(self.shape,translate(pad_button_6mm,-.125,-.08,0))
+      self.pad.append(point(-.125,-.08,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'R1'))
+      #
+      # right 2
+      #
+      self.shape = add(self.shape,translate(pad_button_6mm,.125,-.08,0))
+      self.pad.append(point(.125,-.08,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'R2'))
+      #
+      # left 2
+      #
+      self.shape = add(self.shape,translate(pad_button_6mm,.125,.08,0))
+      self.pad.append(point(.125,.08,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'L2'))
+
+############################################################
+# crystals and resonators
+############################################################
+
+pad_XTAL_EFOBM = cube(-.016,.016,-.085,.085,0,0)
+
+class XTAL_EFOBM(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_EFOBM,-.053,0,0)
+      self.pad.append(point(-.053,0,0))
+      #
+      # ground
+      #
+      self.shape = add(self.shape,translate(pad_XTAL_EFOBM,0,0,0))
+      self.pad.append(point(0,0,0))
+      #
+      # right
+      #
+      self.shape = add(self.shape,translate(pad_XTAL_EFOBM,.053,0,0))
+      self.pad.append(point(.053,0,0))
+
+pad_XTAL_NX5032GA = cube(-.039,.039,-.047,.047,0,0)
+.079
+
+class XTAL_NX5032GA(part):
+   #
+   # NDK NX5032GA
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # left
+      #
+      self.shape = translate(pad_XTAL_NX5032GA,-.079,0,0)
+      self.pad.append(point(-.079,0,0))
+      #
+      # right
+      #
+      self.shape = add(self.shape,translate(pad_XTAL_NX5032GA,.079,0,0))
+      self.pad.append(point(.079,0,0))
+
+pad_XTAL_CSM_7 = cube(-.108,.108,-.039,.039,0,0)
+
+class XTAL_CSM_7(part):
+   #
+   # ECS CSM-7 series
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # left
+      #
+      self.shape = translate(pad_XTAL_CSM_7,-.187,0,0)
+      self.pad.append(point(-.187,0,0))
+      #
+      # right
+      #
+      self.shape = add(self.shape,translate(pad_XTAL_CSM_7,.187,0,0))
+      self.pad.append(point(.187,0,0))
+
+############################################################
+# diodes, transistors, regulators, sensors
+############################################################
+
+class DRV8428_HTSSOP(part):
+   #
+   # TI DRV8428PWPR stepper driver
+   #    HTSSOP package
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      d = 0.12
+      w = 0.029
+      h = 0.0053
+      p = 0.02559
+      pad = cube(-w,w,-h,h,0,0)
+      s = 0.003
+      #
+      # pin 1
+      #
+      self.shape = translate(pad,-d,3.5*p,0)
+      self.shape = add(self.shape,cylinder(-d-w,3.5*p,0,0,h))
+      self.pad.append(point(-d,3.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'.VM',line=s))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad,-d,2.5*p,0))
+      self.pad.append(point(-d,2.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PGND',line=s))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad,-d,1.5*p,0))
+      self.pad.append(point(-d,1.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'AOUT1',line=s))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad,-d,.5*p,0))
+      self.pad.append(point(-d,.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'AOUT2',line=s))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.5*p,0))
+      self.pad.append(point(-d,-.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'BOUT2',line=s))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad,-d,-1.5*p,0))
+      self.pad.append(point(-d,-1.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'BOUT1',line=s))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad,-d,-2.5*p,0))
+      self.pad.append(point(-d,-2.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=s))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(pad,-d,-3.5*p,0))
+      self.pad.append(point(-d,-3.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DVDD',line=s))
+      #
+      # pin 9
+      #
+      self.shape = add(self.shape,translate(pad,d,-3.5*p,0))
+      self.pad.append(point(d,-3.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VREF',line=s))
+      #
+      # pin 10
+      #
+      self.shape = add(self.shape,translate(pad,d,-2.5*p,0))
+      self.pad.append(point(d,-2.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'M0',line=s))
+      #
+      # pin 11
+      #
+      self.shape = add(self.shape,translate(pad,d,-1.5*p,0))
+      self.pad.append(point(d,-1.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DECAY',line=s))
+      #
+      # pin 12
+      #
+      self.shape = add(self.shape,translate(pad,d,-.5*p,0))
+      self.pad.append(point(d,-.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'M1',line=s))
+      #
+      # pin 13
+      #
+      self.shape = add(self.shape,translate(pad,d,.5*p,0))
+      self.pad.append(point(d,.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'STEP',line=s))
+      #
+      # pin 14
+      #
+      self.shape = add(self.shape,translate(pad,d,1.5*p,0))
+      self.pad.append(point(d,1.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DIR',line=s))
+      #
+      # pin 15
+      #
+      self.shape = add(self.shape,translate(pad,d,2.5*p,0))
+      self.pad.append(point(d,2.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'EN',line=s))
+      #
+      # pin 16
+      #
+      self.shape = add(self.shape,translate(pad,d,3.5*p,0))
+      self.pad.append(point(d,3.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SLEEP',line=s))
+      #
+      # pin 17
+      #
+      self.shape = add(self.shape,translate(cube(-.06,.06,-.09,.09,0,0),0,0,0))
+      self.pad.append(point(0,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=s))
+
+class LED_3014_1100(part):
+   #
+   # Luminus MP-3014-1100-50-80
+   #
+   def __init__(self,value=''):
+      anode = cube(-.011,.011,-.027,.027,0,0)
+      cathode = cube(-.036,.036,-.027,.027,0,0)
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # anode
+      #
+      self.shape = translate(anode,-.047,0,0)
+      self.pad.append(point(-.047,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A'))
+      #
+      # cathode
+      #
+      self.shape = add(self.shape,translate(cathode,.022,0,0))
+      self.pad.append(point(.022,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'C'))
+
+class CMM4030D261I2STR(part):
+   #
+   # CUI CMM-4030D-261-I2S-TR I2S microphone
+   #
+   def __init__(self,value=''):
+      pad = cube(-.018,.018,-.011,.011,0,0)
+      self.value = value
+      self.x = 0
+      self.y = 0
+      self.z = 0
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      s = 0.004
+      #
+      # pin 1
+      #
+      self.shape = translate(pad,.037,-.059,0)
+      self.pad.append(point(.037,-.059,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND.',line=s))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad,.037,-.019,0))
+      self.pad.append(point(.037,-.019,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'N/C',line=s))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad,.037,.019,0))
+      self.pad.append(point(.037,.019,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'WS',line=s))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad,.037,.059,0))
+      self.pad.append(point(.037,.059,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'EN',line=s))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad,-.037,.059,0))
+      self.pad.append(point(-.037,.059,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'L/R',line=s))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad,-.037,.019,0))
+      self.pad.append(point(-.037,.019,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCK',line=s))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad,-.037,-.019,0))
+      self.pad.append(point(-.037,-.019,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SD',line=s))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(pad,-.037,-.059,0))
+      self.pad.append(point(-.037,-.059,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VDD',line=s))
+
+class SPG08P4HM4H(part):
+   #
+   # Knowles SPG08P4HM4H-1 PDM microphone
+   #
+   def __init__(self,value=''):
+      pad = cube(-.011,.011,-.011,.011,0,0)
+      self.value = value
+      self.x = 0
+      self.y = 0
+      self.z = 0
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      s = 0.004
+      #
+      # pin 1
+      #
+      self.shape = translate(pad,.023,-.037,0)
+      self.pad.append(point(.023,-.037,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V.',line=s))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad,.023,0,0))
+      self.pad.append(point(.023,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G',line=s))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad,.023,.037,0))
+      self.pad.append(point(.023,.037,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DAT',line=s))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad,-.023,.037,0))
+      self.pad.append(point(-.023,.037,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CK',line=s))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad,-.023,0,0))
+      self.pad.append(point(-.023,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G',line=s))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad,-.023,-.037,0))
+      self.pad.append(point(-.023,-.037,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SEL',line=s))
+
+class VEML6040(part):
+   #
+   # Vishay VEML6040 color sensor 
+   #
+   def __init__(self,value=''):
+      pad12 = cube(-.016,.019,-.006,.006,0,0)
+      pad3 = cube(-.023,.016,-.006,.006,0,0)
+      pad4 = cube(-.019,.016,-.006,.006,0,0)
+      self.value = value
+      self.x = 0
+      self.y = 0
+      self.z = 0
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      s = 0.004
+      #
+      # pin 1
+      #
+      self.shape = translate(pad12,-.039,.014,0)
+      self.pad.append(point(-.039,.014,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1GND',line=s))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad12,-.039,-.014,0))
+      self.pad.append(point(-.039,-.014,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SDA',line=s))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad3,.039,-.014,0))
+      self.pad.append(point(.039,-.014,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCL',line=s))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad4,.039,.014,0))
+      self.pad.append(point(.039,.014,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VDD',line=s))
+
+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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A'))
+      #
+      # cathode
+      #
+      self.shape = add(self.shape,translate(pad_1206,.06,0,0))
+      self.pad.append(point(.055,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'C'))
+
+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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A'))
+      #
+      # cathode
+      #
+      self.shape = add(self.shape,translate(pad_1206,.06,0,0))
+      self.pad.append(point(.055,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'C'))
+
+pad_RGB = cube(-.02,.02,-.029,.029,0,0)
+
+class LED_RGB(part):
+   #
+   # CREE CLV1A-FKB
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.x = 0
+      self.y = 0
+      self.z = 0
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      dx = .029
+      dy = .059
+      #
+      # pin 1: red
+      #
+      self.shape = translate(pad_RGB,-dx,-dy,0)
+      self.shape = add(self.shape,cylinder(-dx,-dy-.029,0,0,.02))
+      self.pad.append(point(-dx,-dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'R'))
+      #
+      # pin 2: anode
+      #
+      self.shape = add(self.shape,translate(pad_RGB,dx,-dy,0))
+      self.pad.append(point(dx,-dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A'))
+      #
+      # pin 3: blue
+      #
+      self.shape = add(self.shape,translate(pad_RGB,dx,dy,0))
+      self.pad.append(point(dx,dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'B'))
+      #
+      # pin 4: green
+      #
+      self.shape = add(self.shape,translate(pad_RGB,-dx,dy,0))
+      self.pad.append(point(-dx,dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G'))
+
+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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'C'))
+      #
+      # emitter
+      #
+      self.shape = add(self.shape,translate(pad_1206,.06,0,0))
+      self.pad.append(point(.055,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'E'))
+
+pad_PLCC2 = cube(-.029,.029,-.059,.059,0,0)
+
+class phototransistor_PLCC2(part):
+   #
+   # PLCC2 phototransistor
+   # Optek OP580
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # collector
+      #
+      self.shape = translate(pad_PLCC2,-.065,0,0)
+      self.pad.append(point(-.065,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'C'))
+      #
+      # emitter
+      #
+      self.shape = add(self.shape,translate(pad_PLCC2,.065,0,0))
+      self.pad.append(point(.065,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'E'))
+
+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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A'))
+      #
+      # cathode
+      #
+      self.shape = add(self.shape,translate(pad_SOD_123,.07,0,0))
+      self.pad.append(point(.07,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'C'))
+
+pad_SOT23 = cube(-.02,.02,-.012,.012,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,.045,-.0375,0)
+      self.pad.append(point(.045,-.0375,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G'))
+      #
+      # pin 2: source
+      #
+      self.shape = add(self.shape,translate(pad_SOT23,.045,.0375,0))
+      self.pad.append(point(.045,.0375,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'S'))
+      #
+      # pin 3: drain
+      #
+      self.shape = add(self.shape,translate(pad_SOT23,-.045,0,0))
+      self.pad.append(point(-.045,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'D'))
+
+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,.045,-.0375,0)
+      self.pad.append(point(.045,-.0375,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G'))
+      #
+      # pin 2: source
+      #
+      self.shape = add(self.shape,translate(pad_SOT23,.045,.0375,0))
+      self.pad.append(point(.045,.0375,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'S'))
+      #
+      # pin 3: drain
+      #
+      self.shape = add(self.shape,translate(pad_SOT23,-.045,0,0))
+      self.pad.append(point(-.045,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'D'))
+
+class NMOSFET_TO252AA(part):
+   #
+   # Fairchild RFD16N05LSM
+   #
+   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(cube(-.031,.031,-.059,.059,0,0),-.090,0,0)
+      self.pad.append(point(-.090,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G 1'))
+      #
+      # pin 2: source
+      #
+      self.shape = add(self.shape,translate(cube(-.031,.031,-.059,.059,0,0),.090,0,0))
+      self.pad.append(point(.090,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'S'))
+      #
+      # pin 3: drain
+      #
+      self.shape = add(self.shape,translate(cube(-.132,.132,-.132,.132,0,0),0,.261,0))
+      self.pad.append(point(0,.261,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'D'))
+
+class Hall_SOT23(part):
+   #
+   # Allegro A1324
+   #
+   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,-.045,.0375,0)
+      self.pad.append(point(-.045,.0375,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Vcc'))
+      #
+      # pin 2: input
+      #
+      self.shape = add(self.shape,translate(pad_SOT23,-.045,-.0375,0))
+      self.pad.append(point(-.045,-.0375,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'out'))
+      #
+      # pin 3: ground
+      #
+      self.shape = add(self.shape,translate(pad_SOT23,.045,0,0))
+      self.pad.append(point(.045,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'gnd'))
+
+class regulator_SOT23(part):
+   #
+   # TI LM3480IM3
+   #
+   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,-.045,.0375,0)
+      self.pad.append(point(-.045,.0375,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'out'))
+      #
+      # pin 2: input
+      #
+      self.shape = add(self.shape,translate(pad_SOT23,-.045,-.0375,0))
+      self.pad.append(point(-.045,-.0375,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'in'))
+      #
+      # pin 3: ground
+      #
+      self.shape = add(self.shape,translate(pad_SOT23,.045,0,0))
+      self.pad.append(point(.045,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'gnd'))
+
+class regulator_SOT223(part):
+   #
+   # Zetex ZLDO1117
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.x = 0
+      self.y = 0
+      self.z = 0
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      pad_SOT223 = cube(-.02,.02,-.03,.03,0,0)
+      pad_SOT223_ground = cube(-.065,.065,-.03,.03,0,0)
+      #
+      # pin 1: GND
+      #
+      self.shape = translate(pad_SOT223,-.09,-.12,0)
+      self.pad.append(point(-.09,-.12,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1G'))
+      #
+      # pin 2: output
+      #
+      self.shape = add(self.shape,translate(pad_SOT223,0,-.12,0))
+      self.pad.append(point(0,-.12,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'O'))
+      #
+      # pin 3: input
+      #
+      self.shape = add(self.shape,translate(pad_SOT223,.09,-.12,0))
+      self.pad.append(point(.09,-.12,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'I'))
+      #
+      # pin 4: output
+      #
+      self.shape = add(self.shape,translate(pad_SOT223_ground,0,.12,0))
+      self.pad.append(point(0,.12,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'out'))
+
+class A4953_SOICN(part):
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: GND
+      #
+      self.shape = translate(pad_SOIC,-.11,.075,0)
+      self.shape = add(self.shape,cylinder(-.153,.075,0,0,.015))
+      self.pad.append(point(-.11,.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 2: IN2
+      #
+      self.shape = add(self.shape,translate(pad_SOIC,-.11,.025,0))
+      self.pad.append(point(-.11,.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IN2'))
+      #
+      # pin 3: IN1
+      #
+      self.shape = add(self.shape,translate(pad_SOIC,-.11,-.025,0))
+      self.pad.append(point(-.11,-.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IN1'))
+      #
+      # pin 4: VREF
+      #
+      self.shape = add(self.shape,translate(pad_SOIC,-.11,-.075,0))
+      self.pad.append(point(-.11,-.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VREF'))
+      #
+      # pin 5: VBB
+      #
+      self.shape = add(self.shape,translate(pad_SOIC,.11,-.075,0))
+      self.pad.append(point(.11,-.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VBB'))
+      #
+      # pin 6: OUT1
+      #
+      self.shape = add(self.shape,translate(pad_SOIC,.11,-.025,0))
+      self.pad.append(point(.11,-.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'OUT1'))
+      #
+      # pin 7: LSS
+      #
+      self.shape = add(self.shape,translate(pad_SOIC,.11,.025,0))
+      self.pad.append(point(.11,.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'LSS'))
+      #
+      # pin 8: OUT2
+      #
+      self.shape = add(self.shape,translate(pad_SOIC,.11,.075,0))
+      self.pad.append(point(.11,.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'OUT2'))
+      #
+      # thermal pad
+      #
+      self.shape = add(self.shape,rectangle(-.04,.04,-.075,.075))
+
+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.shape = add(self.shape,cylinder(-d-.035,.09,0,0,.016))
+      self.pad.append(point(-d,.09,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GRN'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SN'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GLN'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GLP'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DL'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SP'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DR'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GRP'))
+
+pad_mic = cylinder(0,0,0,0,.02)
+
+class mic_SPU0414HR5H(part):
+   #
+   # Knowles SPU0414HR5H-SB
+   #
+   def __init__(self,value=''):
+      s = 0.004
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: Vdd
+      #
+      self.shape = translate(pad_mic,.033,.048,0)
+      self.pad.append(point(.033,.048,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V1',line=s))
+      #
+      # pin 2: GND
+      #
+      self.shape = add(self.shape,translate(pad_mic,.033,-.048,0))
+      self.pad.append(point(.033,-.048,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=s))
+      #
+      # pin 3: gain
+      #
+      self.shape = add(self.shape,translate(pad_mic,-.033,-.048,0))
+      self.pad.append(point(-.033,-.048,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'gain',line=s))
+      #
+      # pin 4: out
+      #
+      self.shape = add(self.shape,translate(pad_mic,-.033,.048,0))
+      self.pad.append(point(-.033,.048,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'out',line=s))
+
+class mic_SPM1437(part):
+   #
+   # Knowles SPM1437HM4H-B
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_mic,-.046,.065,0)
+      #self.shape = add(self.shape,cylinder(-.183,.075,0,0,.015))
+      self.pad.append(point(-.046,.065,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_mic,-.046,0,0))
+      self.pad.append(point(-.046,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SEL'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_mic,-.046,-.065,0))
+      self.pad.append(point(-.046,-.065,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_mic,.046,-.065,0))
+      self.pad.append(point(.046,-.065,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CLK'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad_mic,.046,0,0))
+      self.pad.append(point(.046,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DAT'))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad_mic,.046,.065,0))
+      self.shape = add(self.shape,translate(pad_mic,.038,.057,0))
+      self.pad.append(point(.046,.065,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V'))
+
+pad_accel = cube(-.03,.03,-.0125,.0125,0,0)
+pad_accel90 = cube(-.0125,.0125,-.03,.03,0,0)
+
+class accel_MXD6235M(part):
+   #
+   # MEMSIC MXD6235M
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_accel,-.1,.05,0)
+      self.shape = add(self.shape,cylinder(-.13,.05,0,0,.0125))
+      self.pad.append(point(-.1,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_accel,-.1,0,0))
+      self.pad.append(point(-.1,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'TP'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_accel,-.1,-.05,0))
+      self.pad.append(point(-.1,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_accel90,0,-.1,0))
+      self.pad.append(point(0,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'NC'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad_accel,.1,-.05,0))
+      self.pad.append(point(.1,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'NC'))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad_accel,.1,0,0))
+      self.pad.append(point(.1,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Y'))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad_accel,.1,.05,0))
+      self.pad.append(point(.1,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'X'))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(pad_accel90,0,.1,0))
+      self.pad.append(point(0,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V'))
+      #
+      # ground plane
+      #
+      self.shape = add(self.shape,cube(-.05,.05,-.05,.05,0,0))
+
+pad_cc_14_1 = cube(-.014,.014,-.0075,.0075,0,0)
+pad_cc_14_1_90 = cube(-.0075,.0075,-.014,.014,0,0)
+
+class ADXL343(part):
+   #
+   # ADI ADXL343 accelerometer
+   #
+   def __init__(self,value=''):
+      d = 0.8/25.4
+      w = 1.01/25.4
+      s = 0.004
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_cc_14_1,-w,2.5*d,0)
+      self.pad.append(point(-w,2.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,"VD1",line=s))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_cc_14_1,-w,1.5*d,0))
+      self.pad.append(point(-w,1.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=s))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_cc_14_1,-w,.5*d,0))
+      self.pad.append(point(-w,.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RSV',line=s))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_cc_14_1,-w,-.5*d,0))
+      self.pad.append(point(-w,-.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=s))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad_cc_14_1,-w,-1.5*d,0))
+      self.pad.append(point(-w,-1.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=s))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad_cc_14_1,-w,-2.5*d,0))
+      self.pad.append(point(-w,-2.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VS',line=s))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad_cc_14_1_90,0,-2.5*d,0))
+      self.pad.append(point(0,-2.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'-CS',angle=90,line=s))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(pad_cc_14_1,w,-2.5*d,0))
+      self.pad.append(point(w,-2.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'INT1',line=s))
+      #
+      # pin 9
+      #
+      self.shape = add(self.shape,translate(pad_cc_14_1,w,-1.5*d,0))
+      self.pad.append(point(w,-1.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'INT2',line=s))
+      #
+      # pin 10
+      #
+      self.shape = add(self.shape,translate(pad_cc_14_1,w,-.5*d,0))
+      self.pad.append(point(w,-.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'NC',line=s))
+      #
+      # pin 11
+      #
+      self.shape = add(self.shape,translate(pad_cc_14_1,w,.5*d,0))
+      self.pad.append(point(w,.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RSV',line=s))
+      #
+      # pin 12
+      #
+      self.shape = add(self.shape,translate(pad_cc_14_1,w,1.5*d,0))
+      self.pad.append(point(w,1.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'ALT',line=s))
+      #
+      # pin 13
+      #
+      self.shape = add(self.shape,translate(pad_cc_14_1,w,2.5*d,0))
+      self.pad.append(point(w,2.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SDA',line=s))
+      #
+      # pin 14
+      #
+      self.shape = add(self.shape,translate(pad_cc_14_1_90,0,2.5*d,0))
+      self.pad.append(point(0,2.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCL',angle=90,line=s))
+
+class VL53L1X(part):
+   #
+   # ST VL53L1X time of flight sensor 
+   #
+   def __init__(self,value=''):
+      pad = cube(-.0075,.0075,-.0075,.0075,0,0)
+      d = 0.8/25.4
+      w = 0.8/25.4
+      s = 0.004
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad,-w,-2*d,0)
+      self.pad.append(point(-w,-2*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,"1V",line=s))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad,-w,-1*d,0))
+      self.pad.append(point(-w,-1*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G',line=s))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad,-w,0*d,0))
+      self.pad.append(point(-w,0*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G',line=s))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad,-w,1*d,0))
+      self.pad.append(point(-w,1*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G',line=s))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad,-w,2*d,0))
+      self.pad.append(point(-w,2*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'XS',line=s))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad,0,2*d,0))
+      self.pad.append(point(0,2*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G',line=s))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad,w,2*d,0))
+      self.pad.append(point(w,2*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO',line=s))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(pad,w,1*d,0))
+      self.pad.append(point(w,1*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'NC',line=s))
+      #
+      # pin 9
+      #
+      self.shape = add(self.shape,translate(pad,w,0*d,0))
+      self.pad.append(point(w,0*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SDA',line=s))
+      #
+      # pin 10
+      #
+      self.shape = add(self.shape,translate(pad,w,-1*d,0))
+      self.pad.append(point(w,-1*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCL',line=s))
+      #
+      # pin 11
+      #
+      self.shape = add(self.shape,translate(pad,w,-2*d,0))
+      self.pad.append(point(w,-2*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V',line=s))
+      #
+      # pin 12
+      #
+      self.shape = add(self.shape,translate(pad,0,-2*d,0))
+      self.pad.append(point(0,-2*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G',line=s))
+
+############################################################
+# ICs
+############################################################
+
+class AVRDB28(part):
+   #
+   # AVR*DB28
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      d = 9.01/2/25.4 # spacing
+      w = 0.4/2/25.4 # width
+      h = 1.4/2/25.4 # height
+      p = 0.8/25.4 # pitch
+      l = 0.004 # text
+      pad = cube(-h,h,-w,w,0,0)
+      padv = cube(-w,w,-h,h,0,0)
+      #
+      # pin 1
+      #
+      self.shape = translate(pad,-d,3.5*p,0)
+      self.shape = add(self.shape,cylinder(-d-h,3.5*p,0,0,w))
+      self.pad.append(point(-d,3.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'.PA3',line=l))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad,-d,2.5*p,0))
+      self.pad.append(point(-d,2.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA4',line=l))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad,-d,1.5*p,0))
+      self.pad.append(point(-d,1.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA5',line=l))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad,-d,.5*p,0))
+      self.pad.append(point(-d,.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA6',line=l))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.5*p,0))
+      self.pad.append(point(-d,-.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA7',line=l))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad,-d,-1.5*p,0))
+      self.pad.append(point(-d,-1.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC0',line=l))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad,-d,-2.5*p,0))
+      self.pad.append(point(-d,-2.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC1',line=l))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(pad,-d,-3.5*p,0))
+      self.pad.append(point(-d,-3.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC2',line=l))
+      #
+      # pin 9
+      #
+      self.shape = add(self.shape,translate(padv,-3.5*p,-d,0))
+      self.pad.append(point(-3.5*p,-d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC3',line=l,angle=-90))
+      #
+      # pin 10
+      #
+      self.shape = add(self.shape,translate(padv,-2.5*p,-d,0))
+      self.pad.append(point(-2.5*p,-d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VIO2',line=l,angle=-90))
+      #
+      # pin 11
+      #
+      self.shape = add(self.shape,translate(padv,-1.5*p,-d,0))
+      self.pad.append(point(-1.5*p,-d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD1',line=l,angle=-90))
+      #
+      # pin 12
+      #
+      self.shape = add(self.shape,translate(padv,-.5*p,-d,0))
+      self.pad.append(point(-.5*p,-d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD2',line=l,angle=-90))
+      #
+      # pin 13
+      #
+      self.shape = add(self.shape,translate(padv,.5*p,-d,0))
+      self.pad.append(point(.5*p,-d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD3',line=l,angle=-90))
+      #
+      # pin 14
+      #
+      self.shape = add(self.shape,translate(padv,1.5*p,-d,0))
+      self.pad.append(point(1.5*p,-d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD4',line=l,angle=-90))
+      #
+      # pin 15
+      #
+      self.shape = add(self.shape,translate(padv,2.5*p,-d,0))
+      self.pad.append(point(2.5*p,-d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD5',line=l,angle=-90))
+      #
+      # pin 16
+      #
+      self.shape = add(self.shape,translate(padv,3.5*p,-d,0))
+      self.pad.append(point(3.5*p,-d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD6',line=l,angle=-90))
+      #
+      # pin 17
+      #
+      self.shape = add(self.shape,translate(pad,d,-3.5*p,0))
+      self.pad.append(point(d,-3.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD7',line=l))
+      #
+      # pin 18
+      #
+      self.shape = add(self.shape,translate(pad,d,-2.5*p,0))
+      self.pad.append(point(d,-2.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'AVDD',line=l))
+      #
+      # pin 19
+      #
+      self.shape = add(self.shape,translate(pad,d,-1.5*p,0))
+      self.pad.append(point(d,-1.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=l))
+      #
+      # pin 20
+      #
+      self.shape = add(self.shape,translate(pad,d,-.5*p,0))
+      self.pad.append(point(d,-.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PF0',line=l))
+      #
+      # pin 21
+      #
+      self.shape = add(self.shape,translate(pad,d,.5*p,0))
+      self.pad.append(point(d,.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PF1',line=l))
+      #
+      # pin 22
+      #
+      self.shape = add(self.shape,translate(pad,d,1.5*p,0))
+      self.pad.append(point(d,1.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PF2',line=l))
+      #
+      # pin 23
+      #
+      self.shape = add(self.shape,translate(pad,d,2.5*p,0))
+      self.pad.append(point(d,2.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PF3',line=l))
+      #
+      # pin 24
+      #
+      self.shape = add(self.shape,translate(pad,d,3.5*p,0))
+      self.pad.append(point(d,3.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PF4',line=l))
+      #
+      # pin 25
+      #
+      self.shape = add(self.shape,translate(padv,3.5*p,d,0))
+      self.pad.append(point(3.5*p,d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PF5',line=l,angle=-90))
+      #
+      # pin 26
+      #
+      self.shape = add(self.shape,translate(padv,2.5*p,d,0))
+      self.pad.append(point(2.5*p,d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PF6',line=l,angle=-90))
+      #
+      # pin 27
+      #
+      self.shape = add(self.shape,translate(padv,1.5*p,d,0))
+      self.pad.append(point(1.5*p,d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'UPDI',line=l,angle=-90))
+      #
+      # pin 28
+      #
+      self.shape = add(self.shape,translate(padv,.5*p,d,0))
+      self.pad.append(point(.5*p,d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VDD',line=l,angle=-90))
+      #
+      # pin 29
+      #
+      self.shape = add(self.shape,translate(padv,-.5*p,d,0))
+      self.pad.append(point(-.5*p,d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=l,angle=-90))
+      #
+      # pin 30
+      #
+      self.shape = add(self.shape,translate(padv,-1.5*p,d,0))
+      self.pad.append(point(-1.5*p,d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA0',line=l,angle=-90))
+      #
+      # pin 31
+      #
+      self.shape = add(self.shape,translate(padv,-2.5*p,d,0))
+      self.pad.append(point(-2.5*p,d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA1',line=l,angle=-90))
+      #
+      # pin 32
+      #
+      self.shape = add(self.shape,translate(padv,-3.5*p,d,0))
+      self.pad.append(point(-3.5*p,d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA2',line=l,angle=-90))
+
+class ATtiny3216(part):
+   #
+   # SOIC-20
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      d = 9.82/2/25.4
+      w = .63/2/25.4
+      h = 1.9/2/25.4
+      pad = cube(-h,h,-w,w,0,0)
+      #
+      # pin 1
+      #
+      self.shape = translate(pad,-d,.225,0)
+      self.shape = add(self.shape,cylinder(-d-h,.225,0,0,w))
+      self.pad.append(point(-d,.225,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1VCC'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad,-d,.175,0))
+      self.pad.append(point(-d,.175,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA4'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad,-d,.125,0))
+      self.pad.append(point(-d,.125,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA5'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad,-d,.075,0))
+      self.pad.append(point(-d,.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA6'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad,-d,.025,0))
+      self.pad.append(point(-d,.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA7'))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.025,0))
+      self.pad.append(point(-d,-.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB5'))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.075,0))
+      self.pad.append(point(-d,-.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB4'))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.125,0))
+      self.pad.append(point(-d,-.125,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RB3'))
+      #
+      # pin 9
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.175,0))
+      self.pad.append(point(-d,-.175,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'TB2'))
+      #
+      # pin 10
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.225,0))
+      self.pad.append(point(-d,-.225,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB1'))
+      #
+      # pin 11
+      #
+      self.shape = add(self.shape,translate(pad,d,-.225,0))
+      self.pad.append(point(d,-.225,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0'))
+      #
+      # pin 12
+      #
+      self.shape = add(self.shape,translate(pad,d,-.175,0))
+      self.pad.append(point(d,-.175,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC0'))
+      #
+      # pin 13
+      #
+      self.shape = add(self.shape,translate(pad,d,-.125,0))
+      self.pad.append(point(d,-.125,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC1'))
+      #
+      # pin 14
+      #
+      self.shape = add(self.shape,translate(pad,d,-.075,0))
+      self.pad.append(point(d,-.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC2'))
+      #
+      # pin 15
+      #
+      self.shape = add(self.shape,translate(pad,d,-.025,0))
+      self.pad.append(point(d,-.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC3'))
+      #
+      # pin 16
+      #
+      self.shape = add(self.shape,translate(pad,d,.025,0))
+      self.pad.append(point(d,.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'UPDI'))
+      #
+      # pin 17
+      #
+      self.shape = add(self.shape,translate(pad,d,.075,0))
+      self.pad.append(point(d,.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA1'))
+      #
+      # pin 18
+      #
+      self.shape = add(self.shape,translate(pad,d,.125,0))
+      self.pad.append(point(d,.125,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA2'))
+      #
+      # pin 19
+      #
+      self.shape = add(self.shape,translate(pad,d,.175,0))
+      self.pad.append(point(d,.175,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA3'))
+      #
+      # pin 20
+      #
+      self.shape = add(self.shape,translate(pad,d,.225,0))
+      self.pad.append(point(d,.225,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+
+class SAMD21E(part):
+   #
+   # TQFP
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      d = 9.01/2/25.4 # spacing
+      w = 0.4/2/25.4 # width
+      h = 1.4/2/25.4 # height
+      p = 0.8/25.4 # pitch
+      l = 0.004 # text
+      pad = cube(-h,h,-w,w,0,0)
+      padv = cube(-w,w,-h,h,0,0)
+      #
+      # pin 1
+      #
+      self.shape = translate(pad,-d,3.5*p,0)
+      self.shape = add(self.shape,cylinder(-d-h,3.5*p,0,0,w))
+      self.pad.append(point(-d,3.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1A0',line=l))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad,-d,2.5*p,0))
+      self.pad.append(point(-d,2.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A01',line=l))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad,-d,1.5*p,0))
+      self.pad.append(point(-d,1.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A02',line=l))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad,-d,.5*p,0))
+      self.pad.append(point(-d,.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A03',line=l))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.5*p,0))
+      self.pad.append(point(-d,-.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A04',line=l))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad,-d,-1.5*p,0))
+      self.pad.append(point(-d,-1.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A05',line=l))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad,-d,-2.5*p,0))
+      self.pad.append(point(-d,-2.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A06',line=l))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(pad,-d,-3.5*p,0))
+      self.pad.append(point(-d,-3.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A07',line=l))
+      #
+      # pin 9
+      #
+      self.shape = add(self.shape,translate(padv,-3.5*p,-d,0))
+      self.pad.append(point(-3.5*p,-d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VAN',line=l,angle=-90))
+      #
+      # pin 10
+      #
+      self.shape = add(self.shape,translate(padv,-2.5*p,-d,0))
+      self.pad.append(point(-2.5*p,-d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=l,angle=-90))
+      #
+      # pin 11
+      #
+      self.shape = add(self.shape,translate(padv,-1.5*p,-d,0))
+      self.pad.append(point(-1.5*p,-d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A08',line=l,angle=-90))
+      #
+      # pin 12
+      #
+      self.shape = add(self.shape,translate(padv,-.5*p,-d,0))
+      self.pad.append(point(-.5*p,-d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A09',line=l,angle=-90))
+      #
+      # pin 13
+      #
+      self.shape = add(self.shape,translate(padv,.5*p,-d,0))
+      self.pad.append(point(.5*p,-d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A10',line=l,angle=-90))
+      #
+      # pin 14
+      #
+      self.shape = add(self.shape,translate(padv,1.5*p,-d,0))
+      self.pad.append(point(1.5*p,-d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A11',line=l,angle=-90))
+      #
+      # pin 15
+      #
+      self.shape = add(self.shape,translate(padv,2.5*p,-d,0))
+      self.pad.append(point(2.5*p,-d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A14',line=l,angle=-90))
+      #
+      # pin 16
+      #
+      self.shape = add(self.shape,translate(padv,3.5*p,-d,0))
+      self.pad.append(point(3.5*p,-d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A15',line=l,angle=-90))
+      #
+      # pin 17
+      #
+      self.shape = add(self.shape,translate(pad,d,-3.5*p,0))
+      self.pad.append(point(d,-3.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A16',line=l))
+      #
+      # pin 18
+      #
+      self.shape = add(self.shape,translate(pad,d,-2.5*p,0))
+      self.pad.append(point(d,-2.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A17',line=l))
+      #
+      # pin 19
+      #
+      self.shape = add(self.shape,translate(pad,d,-1.5*p,0))
+      self.pad.append(point(d,-1.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A18',line=l))
+      #
+      # pin 20
+      #
+      self.shape = add(self.shape,translate(pad,d,-.5*p,0))
+      self.pad.append(point(d,-.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A19',line=l))
+      #
+      # pin 21
+      #
+      self.shape = add(self.shape,translate(pad,d,.5*p,0))
+      self.pad.append(point(d,.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A22',line=l))
+      #
+      # pin 22
+      #
+      self.shape = add(self.shape,translate(pad,d,1.5*p,0))
+      self.pad.append(point(d,1.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A23',line=l))
+      #
+      # pin 23
+      #
+      self.shape = add(self.shape,translate(pad,d,2.5*p,0))
+      self.pad.append(point(d,2.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'24-',line=l))
+      #
+      # pin 24
+      #
+      self.shape = add(self.shape,translate(pad,d,3.5*p,0))
+      self.pad.append(point(d,3.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'25+',line=l))
+      #
+      # pin 25
+      #
+      self.shape = add(self.shape,translate(padv,3.5*p,d,0))
+      self.pad.append(point(3.5*p,d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A27',line=l,angle=-90))
+      #
+      # pin 26
+      #
+      self.shape = add(self.shape,translate(padv,2.5*p,d,0))
+      self.pad.append(point(2.5*p,d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RST',line=l,angle=-90))
+      #
+      # pin 27
+      #
+      self.shape = add(self.shape,translate(padv,1.5*p,d,0))
+      self.pad.append(point(1.5*p,d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A28',line=l,angle=-90))
+      #
+      # pin 28
+      #
+      self.shape = add(self.shape,translate(padv,.5*p,d,0))
+      self.pad.append(point(.5*p,d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=l,angle=-90))
+      #
+      # pin 29
+      #
+      self.shape = add(self.shape,translate(padv,-.5*p,d,0))
+      self.pad.append(point(-.5*p,d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCR',line=l,angle=-90))
+      #
+      # pin 30
+      #
+      self.shape = add(self.shape,translate(padv,-1.5*p,d,0))
+      self.pad.append(point(-1.5*p,d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VIN',line=l,angle=-90))
+      #
+      # pin 31
+      #
+      self.shape = add(self.shape,translate(padv,-2.5*p,d,0))
+      self.pad.append(point(-2.5*p,d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CLK',line=l,angle=-90))
+      #
+      # pin 32
+      #
+      self.shape = add(self.shape,translate(padv,-3.5*p,d,0))
+      self.pad.append(point(-3.5*p,d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DIO',line=l,angle=-90))
+
+class SAMD11D(part):
+   #
+   # SOIC-20
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      d = 9.82/2/25.4
+      w = .63/2/25.4
+      h = 1.9/2/25.4
+      pad = cube(-h,h,-w,w,0,0)
+      #
+      # pin 1
+      #
+      self.shape = translate(pad,-d,.225,0)
+      self.shape = add(self.shape,cylinder(-d-h,.225,0,0,w))
+      self.pad.append(point(-d,.225,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1A05'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad,-d,.175,0))
+      self.pad.append(point(-d,.175,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A06'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad,-d,.125,0))
+      self.pad.append(point(-d,.125,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A07'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad,-d,.075,0))
+      self.pad.append(point(-d,.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A08'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad,-d,.025,0))
+      self.pad.append(point(-d,.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A09'))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.025,0))
+      self.pad.append(point(-d,-.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A14'))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.075,0))
+      self.pad.append(point(-d,-.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A15'))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.125,0))
+      self.pad.append(point(-d,-.125,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A16'))
+      #
+      # pin 9
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.175,0))
+      self.pad.append(point(-d,-.175,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A22'))
+      #
+      # pin 10
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.225,0))
+      self.pad.append(point(-d,-.225,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A23'))
+      #
+      # pin 11
+      #
+      self.shape = add(self.shape,translate(pad,d,-.225,0))
+      self.pad.append(point(d,-.225,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RST'))
+      #
+      # pin 12
+      #
+      self.shape = add(self.shape,translate(pad,d,-.175,0))
+      self.pad.append(point(d,-.175,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CLK'))
+      #
+      # pin 13
+      #
+      self.shape = add(self.shape,translate(pad,d,-.125,0))
+      self.pad.append(point(d,-.125,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DIO'))
+      #
+      # pin 14
+      #
+      self.shape = add(self.shape,translate(pad,d,-.075,0))
+      self.pad.append(point(d,-.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'24-'))
+      #
+      # pin 15
+      #
+      self.shape = add(self.shape,translate(pad,d,-.025,0))
+      self.pad.append(point(d,-.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'25+'))
+      #
+      # pin 16
+      #
+      self.shape = add(self.shape,translate(pad,d,.025,0))
+      self.pad.append(point(d,.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 17
+      #
+      self.shape = add(self.shape,translate(pad,d,.075,0))
+      self.pad.append(point(d,.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC'))
+      #
+      # pin 18
+      #
+      self.shape = add(self.shape,translate(pad,d,.125,0))
+      self.pad.append(point(d,.125,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A02'))
+      #
+      # pin 19
+      #
+      self.shape = add(self.shape,translate(pad,d,.175,0))
+      self.pad.append(point(d,.175,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A03'))
+      #
+      # pin 20
+      #
+      self.shape = add(self.shape,translate(pad,d,.225,0))
+      self.pad.append(point(d,.225,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A04'))
+
+class ATtiny1614(part):
+   #
+   # SOIC
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      d = 0.11
+      w = 0.015
+      h = .03
+      pad = cube(-h,h,-w,w,0,0)
+      #
+      # pin 1
+      #
+      self.shape = translate(pad,-d,.15,0)
+      self.shape = add(self.shape,cylinder(-d-h,.15,0,0,w))
+      self.pad.append(point(-d,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'.VCC'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad,-d,.1,0))
+      self.pad.append(point(-d,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA4'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad,-d,.050,0))
+      self.pad.append(point(-d,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA5'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad,-d,0,0))
+      self.pad.append(point(-d,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA6'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.05,0))
+      self.pad.append(point(-d,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA7'))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.1,0))
+      self.pad.append(point(-d,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RB3'))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.15,0))
+      self.pad.append(point(-d,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'TB2'))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(pad,d,-.15,0))
+      self.pad.append(point(d,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB1'))
+      #
+      # pin 9
+      #
+      self.shape = add(self.shape,translate(pad,d,-.1,0))
+      self.pad.append(point(d,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0'))
+      #
+      # pin 10
+      #
+      self.shape = add(self.shape,translate(pad,d,-.05,0))
+      self.pad.append(point(d,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'UPDI'))
+      #
+      # pin 11
+      #
+      self.shape = add(self.shape,translate(pad,d,0,0))
+      self.pad.append(point(d,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA1'))
+      #
+      # pin 12
+      #
+      self.shape = add(self.shape,translate(pad,d,.050,0))
+      self.pad.append(point(d,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA2'))
+      #
+      # pin 13
+      #
+      self.shape = add(self.shape,translate(pad,d,.1,0))
+      self.pad.append(point(d,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA3'))
+      #
+      # pin 14
+      self.shape = add(self.shape,translate(pad,d,.15,0))
+      self.pad.append(point(d,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+
+class FT230XS(part):
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      d = 0.11
+      w = 0.0053
+      h = .03
+      p = .65/25.4
+      l = 0.004
+      pad = cube(-h,h,-w,w,0,0)
+      #
+      # pin 1
+      #
+      self.shape = translate(pad,-d,3.5*p,0)
+      self.shape = add(self.shape,cylinder(-d-h,3.5*p,0,0,w))
+      self.pad.append(point(-d,3.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1TXD',line=l))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad,-d,2.5*p,0))
+      self.pad.append(point(-d,2.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RTS',line=l))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad,-d,1.5*p,0))
+      self.pad.append(point(-d,1.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VIO',line=l))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad,-d,.5*p,0))
+      self.pad.append(point(-d,.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RXD',line=l))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.5*p,0))
+      self.pad.append(point(-d,-.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=l))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad,-d,-1.5*p,0))
+      self.pad.append(point(-d,-1.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CTS',line=l))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad,-d,-2.5*p,0))
+      self.pad.append(point(-d,-2.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CB2',line=l))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(pad,-d,-3.5*p,0))
+      self.pad.append(point(-d,-3.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'USP',line=l))
+      #
+      # pin 9
+      #
+      self.shape = add(self.shape,translate(pad,d,-3.5*p,0))
+      self.pad.append(point(d,-3.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'USM',line=l))
+      #
+      # pin 10
+      #
+      self.shape = add(self.shape,translate(pad,d,-2.5*p,0))
+      self.pad.append(point(d,-2.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'3V3',line=l))
+      #
+      # pin 11
+      #
+      self.shape = add(self.shape,translate(pad,d,-1.5*p,0))
+      self.pad.append(point(d,-1.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RST',line=l))
+      #
+      # pin 12
+      #
+      self.shape = add(self.shape,translate(pad,d,-.5*p,0))
+      self.pad.append(point(d,-.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC',line=l))
+      #
+      # pin 13
+      #
+      self.shape = add(self.shape,translate(pad,d,.5*p,0))
+      self.pad.append(point(d,.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=l))
+      #
+      # pin 14
+      self.shape = add(self.shape,translate(pad,d,1.5*p,0))
+      self.pad.append(point(d,1.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CB1',line=l))
+      #
+      # pin 15
+      #
+      self.shape = add(self.shape,translate(pad,d,2.5*p,0))
+      self.pad.append(point(d,2.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CB0',line=l))
+      #
+      # pin 16
+      self.shape = add(self.shape,translate(pad,d,3.5*p,0))
+      self.pad.append(point(d,3.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CB3',line=l))
+
+
+class ATtiny412(part):
+   #
+   # SOIC150
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      d = 0.11
+      w = 0.015
+      h = .03
+      pad = cube(-h,h,-w,w,0,0)
+      #
+      # pin 1: VCC
+      #
+      self.shape = translate(pad,-d,.075,0)
+      self.shape = add(self.shape,cylinder(-d-h,.075,0,0,w))
+      self.pad.append(point(-d,.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC'))
+      #
+      # pin 2: PA6
+      #
+      self.shape = add(self.shape,translate(pad,-d,.025,0))
+      self.pad.append(point(-d,.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA6'))
+      #
+      # pin 3: PA7
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.025,0))
+      self.pad.append(point(-d,-.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA7'))
+      #
+      # pin 4: PA1
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.075,0))
+      self.pad.append(point(-d,-.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA1'))
+      #
+      # pin 5: PA2
+      #
+      self.shape = add(self.shape,translate(pad,d,-.075,0))
+      self.pad.append(point(d,-.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA2'))
+      #
+      # pin 6: UPDI
+      #
+      self.shape = add(self.shape,translate(pad,d,-.025,0))
+      self.pad.append(point(d,-.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'UPDI'))
+      #
+      # pin 7: PA3
+      #
+      self.shape = add(self.shape,translate(pad,d,.025,0))
+      self.pad.append(point(d,.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA3'))
+      #
+      # pin 8: GND
+      #
+      self.shape = add(self.shape,translate(pad,d,.075,0))
+      self.pad.append(point(d,.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+
+class SAMD11C(part):
+   #
+   # SOIC
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      d = 0.11
+      w = 0.015
+      h = .03
+      pad = cube(-h,h,-w,w,0,0)
+      #
+      # pin 1: PA05
+      #
+      self.shape = translate(pad,-d,.15,0)
+      self.shape = add(self.shape,cylinder(-d-h,.15,0,0,w))
+      self.pad.append(point(-d,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1A05'))
+      #
+      # pin 2: PA08
+      #
+      self.shape = add(self.shape,translate(pad,-d,.1,0))
+      self.pad.append(point(-d,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A08'))
+      #
+      # pin 3: PA09
+      #
+      self.shape = add(self.shape,translate(pad,-d,.050,0))
+      self.pad.append(point(-d,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A09'))
+      #
+      # pin 4: PA14
+      #
+      self.shape = add(self.shape,translate(pad,-d,0,0))
+      self.pad.append(point(-d,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A14'))
+      #
+      # pin 5: PA15
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.05,0))
+      self.pad.append(point(-d,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A15'))
+      #
+      # pin 6: nRESET
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.1,0))
+      self.pad.append(point(-d,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RST'))
+      #
+      # pin 7: CLK
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.15,0))
+      self.pad.append(point(-d,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CLK'))
+      #
+      # pin 8: DIO
+      #
+      self.shape = add(self.shape,translate(pad,d,-.15,0))
+      self.pad.append(point(d,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DIO'))
+      #
+      # pin 9: PA24/D-
+      #
+      self.shape = add(self.shape,translate(pad,d,-.1,0))
+      self.pad.append(point(d,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'24-'))
+      #
+      # pin 10: PA25/D+
+      #
+      self.shape = add(self.shape,translate(pad,d,-.05,0))
+      self.pad.append(point(d,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'25+'))
+      #
+      # pin 11: GND
+      #
+      self.shape = add(self.shape,translate(pad,d,0,0))
+      self.pad.append(point(d,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 12: VDD
+      #
+      self.shape = add(self.shape,translate(pad,d,.050,0))
+      self.pad.append(point(d,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VDD'))
+      #
+      # pin 13: PA02
+      #
+      self.shape = add(self.shape,translate(pad,d,.1,0))
+      self.pad.append(point(d,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A02'))
+      #
+      # pin 14: PA04
+      #
+      self.shape = add(self.shape,translate(pad,d,.15,0))
+      self.pad.append(point(d,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A04'))
+
+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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'O'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V-'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'I+'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'I-'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V+'))
+
+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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1 Ao'))
+      #
+      # pin 2: A-
+      #
+      self.shape = add(self.shape,translate(pad_SOICN,-.12,.025,0))
+      self.pad.append(point(-.12,.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A-'))
+      #
+      # pin 3: A+
+      #
+      self.shape = add(self.shape,translate(pad_SOICN,-.12,-.025,0))
+      self.pad.append(point(-.12,-.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A+'))
+      #
+      # pin 4: V-
+      #
+      self.shape = add(self.shape,translate(pad_SOICN,-.12,-.075,0))
+      self.pad.append(point(-.12,-.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V-'))
+      #
+      # pin 5: B+
+      #
+      self.shape = add(self.shape,translate(pad_SOICN,.12,-.075,0))
+      self.pad.append(point(.12,-.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'B+'))
+      #
+      # pin 6: B-
+      #
+      self.shape = add(self.shape,translate(pad_SOICN,.12,-.025,0))
+      self.pad.append(point(.12,-.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'B-'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Bo'))
+      #
+      # pin 8: V+
+      #
+      self.shape = add(self.shape,translate(pad_SOICN,.12,.075,0))
+      self.pad.append(point(.12,.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V+'))
+
+TSSOP_pad_width = 0.040
+TSSOP_pad_height = 0.011
+TSSOP_pad_dy = 0.026
+TSSOP_pad_dx = 0.120
+pad_TSSOP = cube(-TSSOP_pad_width/2.0,TSSOP_pad_width/2.0,-TSSOP_pad_height/2.0,TSSOP_pad_height/2.0,0,0)
+
+class TRC102(part):
+   #
+   # RFM TRC102 ISM transceiver
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: SDI
+      #
+      self.shape = translate(pad_TSSOP,-TSSOP_pad_dx,3.5*TSSOP_pad_dy,0)
+      self.pad.append(point(-TSSOP_pad_dx,3.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1 SDI'))
+      #
+      # pin 2: SCK
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,-TSSOP_pad_dx,2.5*TSSOP_pad_dy,0))
+      self.pad.append(point(-TSSOP_pad_dx,2.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCK'))
+      #
+      # pin 3: nCS
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,-TSSOP_pad_dx,1.5*TSSOP_pad_dy,0))
+      self.pad.append(point(-TSSOP_pad_dx,1.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'nCS'))
+      #
+      # pin 4: SDO
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,-TSSOP_pad_dx,0.5*TSSOP_pad_dy,0))
+      self.pad.append(point(-TSSOP_pad_dx,0.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SDO'))
+      #
+      # pin 5: IRQ
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,-TSSOP_pad_dx,-0.5*TSSOP_pad_dy,0))
+      self.pad.append(point(-TSSOP_pad_dx,-0.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IRQ'))
+      #
+      # pin 6: DATA/nFSEL
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,-TSSOP_pad_dx,-1.5*TSSOP_pad_dy,0))
+      self.pad.append(point(-TSSOP_pad_dx,-1.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DATA'))
+      #
+      # pin 7: CR
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,-TSSOP_pad_dx,-2.5*TSSOP_pad_dy,0))
+      self.pad.append(point(-TSSOP_pad_dx,-2.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CR'))
+      #
+      # pin 8: CLKOUT
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,-TSSOP_pad_dx,-3.5*TSSOP_pad_dy,0))
+      self.pad.append(point(-TSSOP_pad_dx,-3.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CLKOUT'))
+      #
+      # pin 9: Xtal/Ref
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,TSSOP_pad_dx,-3.5*TSSOP_pad_dy,0))
+      self.pad.append(point(TSSOP_pad_dx,-3.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Xtal'))
+      #
+      # pin 10: RESET
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,TSSOP_pad_dx,-2.5*TSSOP_pad_dy,0))
+      self.pad.append(point(TSSOP_pad_dx,-2.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RESET'))
+      #
+      # pin 11: GND
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,TSSOP_pad_dx,-1.5*TSSOP_pad_dy,0))
+      self.pad.append(point(TSSOP_pad_dx,-1.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 12: RF_P
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,TSSOP_pad_dx,-0.5*TSSOP_pad_dy,0))
+      self.pad.append(point(TSSOP_pad_dx,-0.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RF_P'))
+      #
+      # pin 13: RF_N
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,TSSOP_pad_dx,0.5*TSSOP_pad_dy,0))
+      self.pad.append(point(TSSOP_pad_dx,0.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RF_N'))
+      #
+      # pin 14: VDD
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,TSSOP_pad_dx,1.5*TSSOP_pad_dy,0))
+      self.pad.append(point(TSSOP_pad_dx,1.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VDD'))
+      #
+      # pin 15: RSSIA
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,TSSOP_pad_dx,2.5*TSSOP_pad_dy,0))
+      self.pad.append(point(TSSOP_pad_dx,2.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RSSIA'))
+      #
+      # pin 16: nINT/DDET
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,TSSOP_pad_dx,3.5*TSSOP_pad_dy,0))
+      self.pad.append(point(TSSOP_pad_dx,3.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'nINT'))
+
+pad_SOIC = cube(-.041,.041,-.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.shape = add(self.shape,cylinder(-.183,.075,0,0,.015))
+      self.pad.append(point(-.14,.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RST'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB3'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB4'))
+      #
+      # pin 4: GND
+      #
+      self.shape = add(self.shape,translate(pad_SOIC,-.14,-.075,0))
+      self.pad.append(point(-.14,-.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB1'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB2'))
+      #
+      # pin 8: VCC
+      #
+      self.shape = add(self.shape,translate(pad_SOIC,.14,.075,0))
+      self.pad.append(point(.14,.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC'))
+
+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.shape = add(self.shape,cylinder(-.155,.15,0,0,.015))
+      self.pad.append(point(-.12,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB1'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB3'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB2'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA7'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA6'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA5'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA4'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA3'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA2'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA1'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA0'))
+      #
+      # pin 14: GND
+      #
+      self.shape = add(self.shape,translate(pad_SOICN,.12,.15,0))
+      self.pad.append(point(.12,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+
+pad_TQFP_h = cube(-.025,.025,-.007,.007,0,0)
+pad_TQFP_v = cube(-.007,.007,-.025,.025,0,0)
+
+class ATxmegaE5_TQFP(part):
+   def __init__(self,value=''):
+      c = .18
+      d = 0.8/25.4
+      s = 0.004
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: GND
+      #
+      self.shape = translate(pad_TQFP_h,-c,3.5*d,0)
+      self.pad.append(point(-c,3.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1 GND',line=s))
+      #
+      # pin 2: PA4
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,2.5*d,0))
+      self.pad.append(point(-c,2.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA4',line=s))
+      #
+      # pin 3: PA3
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,1.5*d,0))
+      self.pad.append(point(-c,1.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA3',line=s))
+      #
+      # pin 4: PA2
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,.5*d,0))
+      self.pad.append(point(-c,.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA2',line=s))
+      #
+      # pin 5: PA1
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,-.5*d,0))
+      self.pad.append(point(-c,-.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA1',line=s))
+      #
+      # pin 6: PA0
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,-1.5*d,0))
+      self.pad.append(point(-c,-1.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA0',line=s))
+      #
+      # pin 7: PDI/DATA
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,-2.5*d,0))
+      self.pad.append(point(-c,-2.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PDI/DATA',line=s))
+      #
+      # pin 8: RST/CLOCK
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,-3.5*d,0))
+      self.pad.append(point(-c,-3.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RST/CLOCK',line=s))
+      #
+      # pin 9: PC7
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-3.5*d,-c,0))
+      self.pad.append(point(-3.5*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC7',angle=90,line=s))
+      #
+      # pin 10: PC6
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-2.5*d,-c,0))
+      self.pad.append(point(-2.5*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC6',angle=90,line=s))
+      #
+      # pin 11: PC5
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-1.5*d,-c,0))
+      self.pad.append(point(-1.5*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC5',angle=90,line=s))
+      #
+      # pin 12: PC4
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-.5*d,-c,0))
+      self.pad.append(point(-.5*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC4',angle=90,line=s))
+      #
+      # pin 13: PC3
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,.5*d,-c,0))
+      self.pad.append(point(.5*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC3',angle=90,line=s))
+      #
+      # pin 14: PC2
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,1.5*d,-c,0))
+      self.pad.append(point(1.5*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC2',angle=90,line=s))
+      #
+      # pin 15: PC1
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,2.5*d,-c,0))
+      self.pad.append(point(2.5*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC1',angle=90,line=s))
+      #
+      # pin 16: PC0
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,3.5*d,-c,0))
+      self.pad.append(point(3.5*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC0',angle=90,line=s))
+      #
+      # pin 17: VCC
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,-3.5*d,0))
+      self.pad.append(point(c,-3.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC',line=s))
+      #
+      # pin 18: GND
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,-2.5*d,0))
+      self.pad.append(point(c,-2.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=s))
+      #
+      # pin 19: PR1
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,-1.5*d,0))
+      self.pad.append(point(c,-1.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PR1',line=s))
+      #
+      # pin 20: PR0
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,-.5*d,0))
+      self.pad.append(point(c,-.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PR0',line=s))
+      #
+      # pin 21: PD7
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,.5*d,0))
+      self.pad.append(point(c,.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD7',line=s))
+      #
+      # pin 22: PD6
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,1.5*d,0))
+      self.pad.append(point(c,1.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD6',line=s))
+      #
+      # pin 23: PD5
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,2.5*d,0))
+      self.pad.append(point(c,2.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD5',line=s))
+      #
+      # pin 24: PD4
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,3.5*d,0))
+      self.pad.append(point(c,3.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD4',line=s))
+      #
+      # pin 25: PD3
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,3.5*d,c,0))
+      self.pad.append(point(3.5*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD3',angle=90,line=s))
+      #
+      # pin 26: PD2
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,2.5*d,c,0))
+      self.pad.append(point(2.5*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD2',angle=90,line=s))
+      #
+      # pin 27: PD1
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,1.5*d,c,0))
+      self.pad.append(point(1.5*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD1',angle=90,line=s))
+      #
+      # pin 28: PD0
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,.5*d,c,0))
+      self.pad.append(point(.5*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD0',angle=90,line=s))
+      #
+      # pin 29: PA7
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-.5*d,c,0))
+      self.pad.append(point(-.5*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA7',angle=90,line=s))
+      #
+      # pin 30: PA6
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-1.5*d,c,0))
+      self.pad.append(point(-1.5*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA6',angle=90,line=s))
+      #
+      # pin 31: PA5
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-2.5*d,c,0))
+      self.pad.append(point(-2.5*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA5',angle=90,line=s))
+      #
+      # pin 32: AVCC
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-3.5*d,c,0))
+      self.pad.append(point(-3.5*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'AVCC',angle=90,line=s))
+
+class ATmega88_TQFP(part):
+   def __init__(self,value=''):
+      c = .18
+      d = .031
+      s = 0.004
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: PD3/PCINT19/OC2B/INT1
+      #
+      self.shape = translate(pad_TQFP_h,-c,3.5*d,0)
+      self.pad.append(point(-c,3.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1 PD3',line=s))
+      #
+      # pin 2: PD4/PCINT20/XCK/T0
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,2.5*d,0))
+      self.pad.append(point(-c,2.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD4',line=s))
+      #
+      # pin 3: GND
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,1.5*d,0))
+      self.pad.append(point(-c,1.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=s))
+      #
+      # pin 4: VCC
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,.5*d,0))
+      self.pad.append(point(-c,.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC',line=s))
+      #
+      # pin 5: GND
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,-.5*d,0))
+      self.pad.append(point(-c,-.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=s))
+      #
+      # pin 6: VCC
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,-1.5*d,0))
+      self.pad.append(point(-c,-1.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC',line=s))
+      #
+      # pin 7: PB6/PCINT6/XTAL1/TOSC1
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,-2.5*d,0))
+      self.pad.append(point(-c,-2.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB6',line=s))
+      #
+      # pin 8: PB7/PCINT7/XTAL2/TOSC2
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,-3.5*d,0))
+      self.pad.append(point(-c,-3.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB7',line=s))
+      #
+      # pin 9: PD5/PCINT21/OC0B/T1
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-3.5*d,-c,0))
+      self.pad.append(point(-3.5*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD5',angle=90,line=s))
+      #
+      # pin 10: PD6/PCINT22/OC0A/AIN0
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-2.5*d,-c,0))
+      self.pad.append(point(-2.5*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD6',angle=90,line=s))
+      #
+      # pin 11: PD7/PCINT23/AIN1
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-1.5*d,-c,0))
+      self.pad.append(point(-1.5*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD7',angle=90,line=s))
+      #
+      # pin 12: PB0/PCINT0/CLKO/ICP1
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-.5*d,-c,0))
+      self.pad.append(point(-.5*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0',angle=90,line=s))
+      #
+      # pin 13: PB1/PCINT1/OC1A
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,.5*d,-c,0))
+      self.pad.append(point(.5*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB1',angle=90,line=s))
+      #
+      # pin 14: PB2/PCINT2/-SS/OC1B
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,1.5*d,-c,0))
+      self.pad.append(point(1.5*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB2',angle=90,line=s))
+      #
+      # pin 15: PB3/PCINT3/OC2A/MOSI
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,2.5*d,-c,0))
+      self.pad.append(point(2.5*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB3',angle=90,line=s))
+      #
+      # pin 16: PB4/PCINT4/MISO
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,3.5*d,-c,0))
+      self.pad.append(point(3.5*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB4',angle=90,line=s))
+      #
+      # pin 17: PB5/SCK/PCINT5
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,-3.5*d,0))
+      self.pad.append(point(c,-3.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB5',line=s))
+      #
+      # pin 18: AVCC
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,-2.5*d,0))
+      self.pad.append(point(c,-2.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'AVCC',line=s))
+      #
+      # pin 19: ADC6
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,-1.5*d,0))
+      self.pad.append(point(c,-1.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'ADC6',line=s))
+      #
+      # pin 20: AREF
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,-.5*d,0))
+      self.pad.append(point(c,-.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'AREF',line=s))
+      #
+      # pin 21: GND
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,.5*d,0))
+      self.pad.append(point(c,.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=s))
+      #
+      # pin 22: ADC7
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,1.5*d,0))
+      self.pad.append(point(c,1.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'ADC7',line=s))
+      #
+      # pin 23: PC0/ADC0/PCINT8
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,2.5*d,0))
+      self.pad.append(point(c,2.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC0',line=s))
+      #
+      # pin 24: PC1/ADC1/PCINT9
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,3.5*d,0))
+      self.pad.append(point(c,3.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC1',line=s))
+      #
+      # pin 25: PC2/ADC2/PCINT10
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,3.5*d,c,0))
+      self.pad.append(point(3.5*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC2',angle=90,line=s))
+      #
+      # pin 26: PC3/ADC3/PCINT11
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,2.5*d,c,0))
+      self.pad.append(point(2.5*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC3',angle=90,line=s))
+      #
+      # pin 27: PC4/ADC4/SDA/PCINT12
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,1.5*d,c,0))
+      self.pad.append(point(1.5*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC4',angle=90,line=s))
+      #
+      # pin 28: PC5/ADC5/SCL/PCINT13
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,.5*d,c,0))
+      self.pad.append(point(.5*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC5',angle=90,line=s))
+      #
+      # pin 29: PC6/-RESET/PCINT14
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-.5*d,c,0))
+      self.pad.append(point(-.5*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC6',angle=90,line=s))
+      #
+      # pin 30: PD0/RXD/PCINT16
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-1.5*d,c,0))
+      self.pad.append(point(-1.5*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD0',angle=90,line=s))
+      #
+      # pin 31: PD1/TXD/PCINT17
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-2.5*d,c,0))
+      self.pad.append(point(-2.5*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD1',angle=90,line=s))
+      #
+      # pin 32: PD2/INT0/PCINT18
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-3.5*d,c,0))
+      self.pad.append(point(-3.5*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD2',angle=90,line=s))
+
+class ATmega644_TQFP(part):
+   def __init__(self,value=''):
+      c = .235
+      d = .031
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: PB5/PCINT13/MOSI
+      #
+      self.shape = translate(pad_TQFP_h,-c,5*d,0)
+      self.pad.append(point(-c,5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'*MOSI (1)'))
+      #
+      # pin 2: PB6/PCINT14/MISO
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,4*d,0))
+      self.pad.append(point(-c,4*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'MISO'))
+      #
+      # pin 3: PB7/PCINT15/SCK
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,3*d,0))
+      self.pad.append(point(-c,3*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCK'))
+      #
+      # pin 4: -RESET
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,2*d,0))
+      self.pad.append(point(-c,2*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'-RESET'))
+      #
+      # pin 5: VCC
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,d,0))
+      self.pad.append(point(-c,d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC'))
+      #
+      # pin 6: GND
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,0,0))
+      self.pad.append(point(-c,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 7: XTAL2
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,-d,0))
+      self.pad.append(point(-c,-d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'XTAL2'))
+      #
+      # pin 8: XTAL1
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,-2*d,0))
+      self.pad.append(point(-c,-2*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'XTAL1'))
+      #
+      # pin 9: PD0/PCINT24/RXD0
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,-3*d,0))
+      self.pad.append(point(-c,-3*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RXD0'))
+      #
+      # pin 10: PD1/PCINT25/TXD0
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,-4*d,0))
+      self.pad.append(point(-c,-4*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'TXD0'))
+      #
+      # pin 11: PD2/PCINT26/INT0
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,-5*d,0))
+      self.pad.append(point(-c,-5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD2'))
+      #
+      # pin 12: PD3/PCINT27/INT1
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-5*d,-c,0))
+      self.pad.append(point(-5*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD3'))
+      #
+      # pin 13: PD4/PCINT28/OC1B
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-4*d,-c,0))
+      self.pad.append(point(-4*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD4'))
+      #
+      # pin 14: PD5/PCINT28/OC1A
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-3*d,-c,0))
+      self.pad.append(point(-3*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD5'))
+      #
+      # pin 15: PD6/PCINT30/OC2B/ICP
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-2*d,-c,0))
+      self.pad.append(point(-2*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD6'))
+      #
+      # pin 16: PD7/PCINT31/OC2A
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-d,-c,0))
+      self.pad.append(point(-d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD7'))
+      #
+      # pin 17: VCC
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,0,-c,0))
+      self.pad.append(point(0,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC'))
+      #
+      # pin 18: GND
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,d,-c,0))
+      self.pad.append(point(d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 19: PC0/PCINT16/SCL
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,2*d,-c,0))
+      self.pad.append(point(2*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC0'))
+      #
+      # pin 20: PC1/PCINT17/SDA
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,3*d,-c,0))
+      self.pad.append(point(3*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC1'))
+      #
+      # pin 21: PC2/PCINT18/TCK
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,4*d,-c,0))
+      self.pad.append(point(4*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC2'))
+      #
+      # pin 22: PC3/PCINT19/TMS
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,5*d,-c,0))
+      self.pad.append(point(5*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC3'))
+      #
+      # pin 23: PC4/TDO/PCINT20
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,-5*d,0))
+      self.pad.append(point(c,-5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC4'))
+      #
+      # pin 24: PC5/TDI/PCINT21
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,-4*d,0))
+      self.pad.append(point(c,-4*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC5'))
+      #
+      # pin 25: PC6/TOSC1/PCINT22
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,-3*d,0))
+      self.pad.append(point(c,-3*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC6'))
+      #
+      # pin 26: PC7/TOSC2/PCINT23
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,-2*d,0))
+      self.pad.append(point(c,-2*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC7'))
+      #
+      # pin 27: AVCC
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,-d,0))
+      self.pad.append(point(c,-d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'AVCC'))
+      #
+      # pin 28: GND
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,0,0))
+      self.pad.append(point(c,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 29: AREF
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,d,0))
+      self.pad.append(point(c,d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'AREF'))
+      #
+      # pin 30: PA7/ADC7/PCINT7
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,2*d,0))
+      self.pad.append(point(c,2*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA7'))
+      #
+      # pin 31: PA6/ADC6/PCINT6
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,3*d,0))
+      self.pad.append(point(c,3*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA6'))
+      #
+      # pin 32: PA5/ADC5/PCINT5
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,4*d,0))
+      self.pad.append(point(c,4*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA5'))
+      #
+      # pin 33: PA4/ADC4/PCINT4
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,5*d,0))
+      self.pad.append(point(c,5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA4'))
+      #
+      # pin 34: PA3/ADC3/PCINT3
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,5*d,c,0))
+      self.pad.append(point(5*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA3'))
+      #
+      # pin 35: PA2/ADC2/PCINT2
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,4*d,c,0))
+      self.pad.append(point(4*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA2'))
+      #
+      # pin 36: PA1/ADC1/PCINT1
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,3*d,c,0))
+      self.pad.append(point(3*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA1'))
+      #
+      # pin 37: PA0/ADC0/PCINT0
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,2*d,c,0))
+      self.pad.append(point(2*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA0'))
+      #
+      # pin 38: VCC
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,d,c,0))
+      self.pad.append(point(d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC'))
+      #
+      # pin 39: GND
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,0,c,0))
+      self.pad.append(point(0,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 40: PB0/XCK0/T0/PCINT8
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-d,c,0))
+      self.pad.append(point(-d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0'))
+      #
+      # pin 41: PB1/T1/CLKO/PCINT9
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-2*d,c,0))
+      self.pad.append(point(-2*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB1'))
+      #
+      # pin 42: PB2/AIN0/INT2/PCINT10
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-3*d,c,0))
+      self.pad.append(point(-3*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB2'))
+      #
+      # pin 43: PB3/AIN1/OC0A/PCINT11
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-4*d,c,0))
+      self.pad.append(point(-4*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB2'))
+      #
+      # pin 44: PB4/-SS/OC0B/PCINT12
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-5*d,c,0))
+      self.pad.append(point(-5*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB4'))
+
+TSSOP_pad_width = 0.040
+TSSOP_pad_height = 0.011
+TSSOP_pad_dy = 0.026
+TSSOP_pad_dx = 0.120
+pad_TSSOP = cube(-TSSOP_pad_width/2.0,TSSOP_pad_width/2.0,-TSSOP_pad_height/2.0,TSSOP_pad_height/2.0,0,0)
+
+class TRC102(part):
+   #
+   # RFM TRC102 ISM transceiver
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: SDI
+      #
+      self.shape = translate(pad_TSSOP,-TSSOP_pad_dx,3.5*TSSOP_pad_dy,0)
+      self.pad.append(point(-TSSOP_pad_dx,3.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1 SDI'))
+      #
+      # pin 2: SCK
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,-TSSOP_pad_dx,2.5*TSSOP_pad_dy,0))
+      self.pad.append(point(-TSSOP_pad_dx,2.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCK'))
+      #
+      # pin 3: nCS
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,-TSSOP_pad_dx,1.5*TSSOP_pad_dy,0))
+      self.pad.append(point(-TSSOP_pad_dx,1.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'nCS'))
+      #
+      # pin 4: SDO
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,-TSSOP_pad_dx,0.5*TSSOP_pad_dy,0))
+      self.pad.append(point(-TSSOP_pad_dx,0.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SDO'))
+      #
+      # pin 5: IRQ
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,-TSSOP_pad_dx,-0.5*TSSOP_pad_dy,0))
+      self.pad.append(point(-TSSOP_pad_dx,-0.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IRQ'))
+      #
+      # pin 6: DATA/nFSEL
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,-TSSOP_pad_dx,-1.5*TSSOP_pad_dy,0))
+      self.pad.append(point(-TSSOP_pad_dx,-1.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DATA'))
+      #
+      # pin 7: CR
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,-TSSOP_pad_dx,-2.5*TSSOP_pad_dy,0))
+      self.pad.append(point(-TSSOP_pad_dx,-2.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CR'))
+      #
+      # pin 8: CLKOUT
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,-TSSOP_pad_dx,-3.5*TSSOP_pad_dy,0))
+      self.pad.append(point(-TSSOP_pad_dx,-3.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CLKOUT'))
+      #
+      # pin 9: Xtal/Ref
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,TSSOP_pad_dx,-3.5*TSSOP_pad_dy,0))
+      self.pad.append(point(TSSOP_pad_dx,-3.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Xtal'))
+      #
+      # pin 10: RESET
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,TSSOP_pad_dx,-2.5*TSSOP_pad_dy,0))
+      self.pad.append(point(TSSOP_pad_dx,-2.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RESET'))
+      #
+      # pin 11: GND
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,TSSOP_pad_dx,-1.5*TSSOP_pad_dy,0))
+      self.pad.append(point(TSSOP_pad_dx,-1.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 12: RF_P
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,TSSOP_pad_dx,-0.5*TSSOP_pad_dy,0))
+      self.pad.append(point(TSSOP_pad_dx,-0.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RF_P'))
+      #
+      # pin 13: RF_N
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,TSSOP_pad_dx,0.5*TSSOP_pad_dy,0))
+      self.pad.append(point(TSSOP_pad_dx,0.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RF_N'))
+      #
+      # pin 14: VDD
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,TSSOP_pad_dx,1.5*TSSOP_pad_dy,0))
+      self.pad.append(point(TSSOP_pad_dx,1.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VDD'))
+      #
+      # pin 15: RSSIA
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,TSSOP_pad_dx,2.5*TSSOP_pad_dy,0))
+      self.pad.append(point(TSSOP_pad_dx,2.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RSSIA'))
+      #
+      # pin 16: nINT/DDET
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,TSSOP_pad_dx,3.5*TSSOP_pad_dy,0))
+      self.pad.append(point(TSSOP_pad_dx,3.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'nINT'))
+
+class CBA(part):
+   #
+   # CBA logo
+   #
+   def __init__(self,r=.02):
+      self.value = ''
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      d = 3*r
+      self.shape = cylinder(0,0,0,0,r)
+      self.shape = add(self.shape,translate(cylinder(0,0,0,0,r),-d,d,0))
+      self.shape = add(self.shape,translate(cube(-r,r,-r,r,0,0),-d,0,0))
+      self.shape = add(self.shape,translate(cube(-r,r,-r,r,0,0),-d,-d,0))
+      self.shape = add(self.shape,translate(cube(-r,r,-r,r,0,0),0,-d,0))
+      self.shape = add(self.shape,translate(cube(-r,r,-r,r,0,0),d,-d,0))
+      self.shape = add(self.shape,translate(cube(-r,r,-r,r,0,0),d,0,0))
+      self.shape = add(self.shape,translate(cube(-r,r,-r,r,0,0),d,d,0))
+      self.shape = add(self.shape,translate(cube(-r,r,-r,r,0,0),0,d,0))
+
+class fab(part):
+   def __init__(self,r=.05):
+      self.value = ''
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      d = 1.8*r
+      l = 3.5*r
+      h = r/2.
+      self.shape = rectangle(-d,d,-d,d)
+      self.shape = subtract(self.shape,circle(0,0,r))
+      self.shape = subtract(self.shape,rectangle(-l,0,-h,h))
+      self.shape = add(self.shape,rectangle(d,l,-h,h))
+      self.shape = add(self.shape,circle(l,0,r))
+      self.shape = add(self.shape,circle(-l,0,r))
+
+############################################################
+# define board
+############################################################
+
+width = 1.99 # board width
+height = 1.99-.34 # board height
+x = 1 # x origin
+y = 1 # y origin
+zt = 0 # top z
+zb = -0.06 # bottom z
+w = .0106 # wire width
+w1 = .015 # thicker wire width
+w2 = .03 # thickest wire width
+mask = .002 # solder mask size
+
+pcb = PCB(x,y,width,height,mask)
+
+IC1 = DRV8428_HTSSOP('IC1\nDRV8428')
+pcb = IC1.add(pcb,x+.56,y+height/2+.25)
+
+pcb = wire(pcb,w,
+   IC1.pad[2],
+   point(IC1.x,IC1.pad[2].y))
+
+pcb = wire(pcb,w,
+   IC1.pad[2],
+   point(IC1.pad[2].x-.075,IC1.pad[2].y))
+
+pcb = wire(pcb,w,
+   IC1.pad[7],
+   point(IC1.x,IC1.pad[7].y))
+
+pcb = wire(pcb,w,
+   IC1.pad[7],
+   point(IC1.pad[7].x-.075,IC1.pad[7].y))
+
+pcb = wire(pcb,w,
+   IC1.pad[9],
+   point(IC1.pad[9].x+.075,IC1.pad[9].y))
+   
+pcb = wire(pcb,w,
+   IC1.pad[11],
+   point(IC1.x,IC1.pad[11].y))
+
+pcb = wire(pcb,w,
+   IC1.pad[11],
+   point(IC1.pad[11].x+.075,IC1.pad[11].y))
+
+J2 = header_4H('J2\nstepper')
+pcb = J2.add(pcb,x+.23,y+height/2,angle=180)
+
+pcb = wire(pcb,w,
+   IC1.pad[3],
+   point(J2.x-.132,IC1.pad[3].y),
+   point(J2.x-.132,J2.pad[1].y),
+   J2.pad[1])
+
+pcb = wire(pcb,w,
+   IC1.pad[4],
+   point(J2.x-.106,IC1.pad[4].y),
+   point(J2.x-.106,J2.pad[2].y),
+   J2.pad[2])
+
+pcb = wire(pcb,w,
+   IC1.pad[5],
+   point(J2.x-.08,IC1.pad[5].y),
+   point(J2.x-.08,J2.pad[3].y),
+   J2.pad[3])
+
+pcb = wire(pcb,w,
+   IC1.pad[6],
+   point(J2.x,IC1.pad[6].y),
+   J2.pad[4])
+
+R1 = ST4EB('R1\n10k')
+pcb = R1.add(pcb,IC1.x-.05,IC1.y-.35)
+
+pcb = wire(pcb,w,
+   IC1.pad[9],
+   point(IC1.pad[9].x,IC1.pad[9].y-.06),
+   point(R1.pad[3].x,IC1.pad[9].y-.06),
+   R1.pad[3])
+
+C1 = C_1206('C1\n1uF')
+pcb = C1.add(pcb,J2.x,J2.pad[1].y-.16,angle=90)
+
+pcb = wire(pcb,w1,
+   C1.pad[1],
+   point(C1.x,y+.37))
+
+pcb = wire(pcb,w,
+   C1.pad[2],
+   point(C1.x+.1,C1.pad[2].y),
+   point(C1.x+.1,IC1.pad[8].y),
+   IC1.pad[8])
+
+R2 = R_1206('R2\n10k')
+pcb = R2.add(pcb,R1.pad[1].x-.02,R1.y-.24,angle=0)
+
+pcb = wire(pcb,w,
+   R2.pad[1],
+   point(R2.pad[1].x,C1.pad[2].y),
+   C1.pad[2])
+
+pcb = wire(pcb,w1,
+   R2.pad[2],
+   point(R1.pad[1].x,R2.y),
+   R1.pad[1])
+
+C2 = C_FND('C2\n100uF')
+pcb = C2.add(pcb,IC1.x+.08,IC1.y+.27,angle=90)
+
+pcb = wire(pcb,w2,
+   C2.pad[2],
+   point(C2.pad[2].x,C2.y-.08))
+
+J4 = header_2H('J4\npower')
+pcb = J4.add(pcb,x+.23,IC1.pad[1].y+.05,angle=180)
+
+pcb = wire(pcb,w,
+   IC1.pad[1],
+   point(J4.x,IC1.pad[1].y))
+
+pcb = wire(pcb,w,
+   IC1.pad[1],
+   point(IC1.pad[1].x+.025,IC1.pad[1].y),
+   point(IC1.pad[1].x+.025,IC1.pad[1].y+w),
+   point(J4.x,IC1.pad[1].y+w))
+
+pcb = wire(pcb,w2,
+   point(C2.pad[1].x-.02,C2.y),
+   point(J4.x+.10,J4.pad[1].y+.01),
+   point(J4.x,J4.pad[1].y+.01),
+   J4.pad[1])
+
+C3 = C_1206('C3\n.01uF')
+pcb = C3.add(pcb,C2.x+.31,C2.y)
+
+pcb = wire(pcb,w2,
+   C2.pad[2],
+   C3.pad[1])
+
+pcb = wire(pcb,w2,
+   C3.pad[2],
+   point(C3.pad[2].x,C3.y+.08),
+   point(C2.pad[1].x,C3.y+.08),
+   C2.pad[1])
+
+IC2 = SAMD11C('IC2\nD11C')
+pcb = IC2.add(pcb,x+width-.62,y+height/2,angle=-90)
+
+J1 = header_SWD_4_1('J1 SWD')
+pcb = J1.add(pcb,IC2.pad[7].x-.14,IC2.y,angle=-90)
+
+pcb = wire(pcb,w1,
+   J1.pad[1],
+   point(J1.pad[1].x,IC2.pad[7].y),
+   IC2.pad[7])
+
+pcb = wire(pcb,w1,
+   J1.pad[2],
+   point(J1.pad[2].x,IC2.pad[8].y),
+   IC2.pad[8])
+
+pcb = wire(pcb,w,
+   J1.pad[3],
+   point(J1.pad[3].x,IC2.pad[6].y+.1),
+   point(IC2.pad[6].x,IC2.pad[6].y+.1),
+   IC2.pad[6])
+
+pcb = wire(pcb,w1,
+   J1.pad[4],
+   point(J1.pad[4].x,IC2.pad[12].y-.08),
+   point(IC2.pad[11].x,IC2.pad[11].y-.08),
+   IC2.pad[11])
+
+pcb = wire(pcb,w1,
+   J1.pad[4],
+   point(J1.pad[4].x,IC2.pad[12].y-.08),
+   point(R1.pad[2].x,IC2.pad[12].y-.08),
+   R1.pad[2])
+
+pcb = wire(pcb,w,
+   IC2.pad[1],
+   point(IC2.pad[1].x,IC2.pad[1].y+.21+.03),
+   point(J1.pad[3].x-.190,IC2.pad[5].y+.21+.03),
+   point(J1.pad[3].x-.200,IC1.pad[16].y),
+   IC1.pad[16])
+
+pcb = wire(pcb,w,
+   point(J1.pad[3].x-.154,IC1.pad[16].y),
+   point(J1.pad[3].x-.174,IC1.pad[15].y),
+   IC1.pad[15])
+
+pcb = wire(pcb,w,
+   IC2.pad[2],
+   point(IC2.pad[2].x,IC2.pad[2].y+.184+.03),
+   point(J1.pad[3].x-.128,IC2.pad[5].y+.184+.03),
+   point(J1.pad[3].x-.148,IC1.pad[14].y),
+   IC1.pad[14])
+
+pcb = wire(pcb,w,
+   IC2.pad[3],
+   point(IC2.pad[3].x,IC2.pad[5].y+.158+.03),
+   point(J1.pad[3].x-.102,IC2.pad[5].y+.158+.03),
+   point(J1.pad[3].x-.122,IC1.pad[13].y),
+   IC1.pad[13])
+
+pcb = wire(pcb,w,
+   IC2.pad[4],
+   point(IC2.pad[4].x,IC2.pad[5].y+.132+.03),
+   point(J1.pad[3].x-.076,IC2.pad[5].y+.132+.03),
+   point(J1.pad[3].x-.096,IC1.pad[12].y),
+   IC1.pad[12])
+
+pcb = wire(pcb,w,
+   IC2.pad[5],
+   point(IC2.pad[5].x,IC2.pad[5].y+.106+.03),
+   point(J1.pad[3].x-.05,IC2.pad[5].y+.106+.03),
+   point(J1.pad[3].x-.09,IC1.pad[10].y),
+   IC1.pad[10])
+
+J3 = USB_A_plug('J3\nUSB')
+pcb = J3.add(pcb,x+width-.29,IC2.y+.025,angle=0)
+
+pcb = wire(pcb,w1,
+   J3.pad[2],
+   point(J3.pad[2].x-.11,J3.pad[2].y),
+   point(J3.pad[2].x-.11,IC2.y+.015),
+   point(IC2.pad[9].x,IC2.y+.015),
+   IC2.pad[9])
+
+pcb = wire(pcb,w1,
+   point(J3.pad[3].x,IC2.y-.015),
+   point(IC2.pad[10].x,IC2.y-.015),
+   IC2.pad[10])
+
+pcb = wire(pcb,w1,
+   J3.pad[4],
+   point(J3.pad[4].x-.11,J3.pad[4].y),
+   point(J3.pad[4].x-.11,IC2.y-.045),
+   point(IC2.pad[11].x,IC2.y-.045),
+   IC2.pad[11])
+
+pcb = wire(pcb,w2,
+   J3.pad[4],
+   point(J3.pad[4].x-.11,J3.pad[4].y),
+   point(J3.pad[4].x-.11,y+.37),
+   point(x+.03,y+.37),
+   point(x+.03,J4.pad[2].y),
+   J4.pad[2])
+
+IC3 = regulator_SOT23('IC3\n3.3V')
+pcb = IC3.add(pcb,IC2.pad[8].x-.1,IC2.pad[9].y-.21,angle=0)
+
+pcb = wire(pcb,w1,
+   J4.pad[1],
+   point(x+.07,J4.pad[1].y),
+   point(x+.07,C1.y),
+   point(C1.x+.08,C1.y),
+   point(C1.x+.08,IC3.pad[2].y-.05),
+   point(IC3.pad[2].x,IC3.pad[2].y-.05),
+   IC3.pad[2])
+
+pcb = wire(pcb,w1,
+   IC3.pad[3],
+   point(IC3.pad[3].x,y+.37))
+
+C4 = C_1206('C4\n1uF')
+pcb = C4.add(pcb,IC3.x-.22,IC3.y)
+
+pcb = wire(pcb,w1,
+   C4.pad[1],
+   point(C4.pad[1].x,C4.y+.1),
+   point(IC3.pad[1].x,C4.y+.1),
+   IC3.pad[1])
+
+pcb = wire(pcb,w1,
+   C4.pad[2],
+   IC3.pad[3])
+
+pcb = wire(pcb,w1,
+   IC3.pad[1],
+   point(IC3.pad[1].x,C4.y+.1),
+   point(IC2.pad[12].x,C4.y+.1),
+   IC2.pad[12])
+
+R3 = R_1206('R3\n0')
+pcb = R3.add(pcb,C3.x+.22,C3.y)
+
+pcb = wire(pcb,w2,
+   C3.pad[2],
+   R3.pad[1])
+
+pcb = wire(pcb,w2,
+   R3.pad[2],
+   point(R3.pad[2].x+.07,R3.pad[2].y),
+   point(R3.pad[2].x+.12,J4.pad[2].y),
+   point(J3.pad[4].x-.11,J4.pad[2].y),
+   point(J3.pad[4].x-.11,J3.pad[1].y),
+   J3.pad[1])
+
+pcb = wire(pcb,w2,
+   IC1.pad[17],
+   point(IC1.x,R3.y-.13),
+   point(IC1.x+.04,R3.y-.08),
+   point(R3.x,R3.y-.08))
+
+pcb = wire(pcb,w2,
+   J4.pad[2],
+   point(J4.x+.11,J4.pad[2].y),
+   point(J4.x+.17,J4.pad[2].y+.06),
+   point(J4.x+.17,C2.y+.07),
+   point(J4.x+.23,C2.y+.13),
+   point(R3.x,C2.y+.13))
+
+pcb = wire(pcb,w1,
+   point(R3.x,R3.y-.08),
+   point(R3.x,C2.y+.13))
+
+R4 = R_1206('R4\n1k')
+pcb = R4.add(pcb,IC2.pad[11].x+.01,IC3.y+.03,angle=0)
+
+pcb = wire(pcb,w1,
+   R4.pad[2],
+   point(IC2.pad[13].x,R4.y),
+   IC2.pad[13])
+
+LED = LED_1206('LED')
+pcb = LED.add(pcb,R4.x,R4.y-.09,angle=180)
+
+pcb = wire(pcb,w1,
+   LED.pad[1],
+   point(IC2.pad[14].x,LED.y),
+   IC2.pad[14])
+
+pcb = wire(pcb,w1,
+   LED.pad[2],
+   point(R4.pad[1].x,LED.y),
+   R4.pad[1])
+
+pcb.holes = add(pcb.holes,cylinder(x+(width-.34)/2,y+height/2,zb,zt,.125))
+pcb.holes = add(pcb.holes,cylinder(x+.21,y+height-.21,zb,zt,.065))
+pcb.holes = add(pcb.holes,cylinder(x+.21,y+.21,zb,zt,.065))
+pcb.holes = add(pcb.holes,cylinder(x+width-(.21+.34),y+height-.21,zb,zt,.065))
+pcb.holes = add(pcb.holes,cylinder(x+width-(.21+.34),y+.21,zb,zt,.065))
+
+l = 0.13
+pcb.exterior = add(pcb.exterior,triangle(x,y+height-l,x,y+height,x+l,y+height))
+pcb.exterior = add(pcb.exterior,triangle(x,y,x,y+l,x+l,y))
+pcb.exterior = add(pcb.exterior,triangle(x+width-.34,y+height,x+width-.34,y+height-l,x+width-l-.34,y+height))
+pcb.exterior = add(pcb.exterior,triangle(x+width-.34-l,y,x+width-.34,y+l,x+width-.34,y))
+pcb.interior = subtract(pcb.interior,triangle(x,y+height-l,x,y+height,x+l,y+height))
+pcb.interior = subtract(pcb.interior,triangle(x,y,x,y+l,x+l,y))
+pcb.interior = subtract(pcb.interior,triangle(x+width-.34,y+height,x+width-.34,y+height-l,x+width-l-.34,y+height))
+pcb.interior = subtract(pcb.interior,triangle(x+width-.34-l,y,x+width-.34,y+l,x+width-.34,y))
+
+#pcb.exterior = add(pcb.exterior,text("8/20/21",x+(width-.34)/2+.1,y+0.2,0,line=0.01,color=White).shape)
+#pcb.exterior = add(pcb.exterior,text("hello.DRV8428-D11C-NEMA17",x+(width-.34)/2,y+0.075,0,line=0.01,color=White).shape)
+#c = CBA(r=0.0125)
+#pcb.exterior = add(pcb.exterior,move(c.shape,x+(width-.34)/2-.175,y+.2))
+
+############################################################
+# select output
+############################################################
+
+outputs = {}
+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, labels, holes, and exterior"):
+   outputs["function"] = add(add(color(Tan,pcb.board),pcb.labels),
+      add(color(White,pcb.exterior),color(Blue,pcb.holes)))
+   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,pcb.board),pcb.labels),
+      add(color(White,pcb.exterior),color(Blue,pcb.holes)))
+   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"] = [zt]
+elif (output == "exterior"):
+   outputs["function"] = color(White,pcb.exterior)
+   outputs["layers"] = [zt]
+elif (output == "holes"):
+   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")
+
+############################################################
+# set limits and parameters
+############################################################
+
+border = 0.05
+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["mm_per_unit"] = 25.4 # use inch units
+outputs["type"] = "RGB" # use RGB color
+
+############################################################
+# send output
+############################################################
+
+json.dump(outputs,sys.stdout)
+
diff --git a/serialstep/board/hello.DRV8428-D11C-NEMA17.holes.png b/serialstep/board/hello.DRV8428-D11C-NEMA17.holes.png
new file mode 100644
index 0000000000000000000000000000000000000000..cf6d3674e63875f56e78e033a2bf1007f138de37
GIT binary patch
literal 17614
zcmeAS@N?(olHy`uVBq!ia0y~y;Lu`VV7tb_#K6Gt@lmiK0|NtRfk$L91H;TyAk6r9
z;u0kW2A2j;7srr_IdASp7Cp9La&TOo^sYYjY`b-p%~RiPa-KRf*$X@rBv>CzTy^_z
zT|FZM2)y{S^A|IS!N9P3qCA+<FyjxHW;pVM9n4Trvj@`*hCd;iI!^L~1sr_pz%)bB
zCx{sWlShph4GV_Rbiu$dnnxH$%L@jEkz97(s9*Pwp<vSOx8MHA@4Wy1{C`l*buD2z
zCqw*>pYDCFs@w<9?<i+rU@%Kr&dI<(Nj~E2LXc2D0|SFt+Hy{Y{R;LQI=rtnz2CWz
zfq`LK;&M)g^AqG}+*3GxaQmGw1_p-U&6imko}c7DlXYP0gX(ws3=9pOH!_(VJn9nc
zf_2#M7fokmVBk6DC(KaviP?B&p5>2e)w~Q02@Ykm7z!rXhu1SyT)CosX!=ikdj^IB
zRcZHEp8fZeF=F<1`56b2PHURWGB6x?`o@IuLB=O$=ja^EAJd}w85kZ2fwc44?>n+X
zEKYFWntyK@7#NOi`4*S+HlO`K$rE<At%ql2w!i0KU@+*DElaenac4+-czn9Vxi)Xr
z?TQQx2Nr_Nthra0pd-DGBfjkKH3kNT=QoPaZ+*U<EkWZGGxN>L+%2EW*%=rt&Yj!6
zcJ6*_2IUFz60M;VK|z>tGhLFAK~KfrfaUeV@MDY&3=5Llzn-#SC=mVG_&SnvZ>k9c
z1H-)Z{IAn4GCUCa#4Ns<t?K*?1_lP3!|PtzCNmxQ`GkF4%Gb}5%FGN5AFRIx&o?w;
znB!CT!04K7ys;ev1A~34`d8D(%m-#ZVPBVc^fSj|76yh77S$`<B~%&wl<f-`v*#X{
z)Mj94aKB+|doF^pfbVDH=E$dirU)`KF#MQRd)Z&okiky@+-?vqp2WwHJW1YSs_Vn|
z66OpH3{hpX7-W3w9@vDLoj0grU|@KEQ``3N3&sMCpN*3vF58@!U}9j{lREv2O)|%U
zLPRU1fQ>&mq(_B;;eht<#a$Cw9w;E%9TszrYeXFrW?(pQZbhmMqeau70~^;Q^d*Ea
zGBnJ+DJ*+%1=9pX>*PSAja8vcGB*Rmo0EAjERKmaOhYt!`W`LpTr8Q$z>r}6&C%WX
z5JL;X3840l@P`CDhBK~p4+O+opBtQGU|`tt#)NUj33#Ju!E?t>W64|wh6MI+cIig9
z7*tRV0F{i5Gt5oSr=MYDXxMu5>zwm5m_OKHZ(SXG8s5N=5cG*zwfoR&iArej*?8h^
zdN~~HcZxgxgPDQh^~TFPr+s99Ac+VkkOvs3)5LRlT(&#*FDOMubj?*`@bRr%P`Lm8
z`hOe@3=BF){e&5o(Wc>;^6vZZtMZB2$K)9pBKqf^+uCCfDi`qj?1TCLkIW4IljJob
zXT=;n!OXz0deeQz22U(4S;PFJ^Ulv;W?;zP{MvH9A^U?$%+PZ<FFgwsu?z?J-qfB;
z*}~|7h<%Vd9>~YlGAvNCFW~5&S}c*yz>pwc=D=Vej)-EJqsf|}w8d~B?@e=GS_>lw
z!YL0N<Yrm)ZDeI&_?BW`B9qMR;Ejmw<DXs}5$w@oVAx<>y+~Oi6jZb^FfbgrwuPOc
zPr<&xqI<@)k1QZ*riPCv`R5$mwINA`k%1xZrhI6R3IjW$m4Cp~#^<9=G6w_0hiS2w
zKKCdx9G@s}(QkUzxJQnG;Xw5_FHr83@j}?W{8PeFa29Sjf5Y%^Um-K7U`*e<@293R
z8w0}!)8EVH8znK!aj1L16lU3P3@W1gH&j>6*~s)j<`eVv4c97L0+|>XD(2W;QSK39
zSUypHM~~?F>plDo3<vygde)x(!BC*~vr#+pd(E*E3=9l^`u<)?@8MxkpDe#)#?|xH
z$5<E`9!QpjzLykcIHzu3V4J;Qdk-4}!-3Cl*4{IcVu*37OW+7|THnLWz~FF{@AcF|
zh6h@om=|x5GXiy<bbsq8GaP7r!p^qo^Qw&J@A()Q3g*l$kG8HaXK+)nH<)I7-L1MV
zn}MOB_|4Aew?0QR8;JaDeE4RY)2+9^nHU)6<ZqvQJ@3AFgW=sj%||xmZNGh0{$a#B
zI|hb^$u~2Z4rK26dtk@4IODZ{QEP-fe-E&TRa+eOWoKY0u(bANu$Tp^VZ2tan7WUf
zf#JZOuv>H2eu-s>=-e(p<Kz|o<vXr3Ffg!zYDM;m@-xntcsrL%GB6x?@WzBuLEYY9
zwdS-ol*%seupaN-NCpOm$(t^-G_?FVpu`p_y9>F}j5w>h+WEU61H*wspt?u=3H!9t
zL$5BpWoBU5AZqQ)P%-Dv0li74i+-~*Ff`PIJR|;u{m1dQ&&n7W7#5@~=R9!kk2WY{
zGcX+a7xNd=4{W%Kn(7%wJAw?OogaqL&JU;x7#%Db(Vd^sK{STZ(ZJCPkzuq#1XTv3
zqk*74FQnBt8Wy8r!7#E%MhAK0VB>#q4{yi4w`JDv`tQI0{`j8-0|P_yuA96}3^`9P
zT>4<KI)H(pVJm3JqFZ{2dCl2HA`A=(hM$-j4m2(E;G4hEft7(FqTvq%!-l?<s}EO)
ztzuwc_&iCTf#KP<h@u}oq1p@#2V$PEGc;)C2Fc#rT*J!1Fr(=Y1B1cL+{1^X#Wpf9
zFf@aP>z*yJsyUG*#=wx^12X(YOM8CgWhMrO9=AFM28k)JK5&a|2dSMP&%n^8Y-4j$
zNSuM;K@mu;LreRFRy_uAho7NAk%OOo;~iE8h8-<`7#Io+A3kIe+snWJ8d_jr&{MXV
zbLJ9ArwM4xnt@^VCAo8;!8r!M$8Xsg8a7+9?4M(5z`$_eBFN33IryD73b8RTSoF!q
zGcj0nelw5?2MtYF+^b_?u$Ytl?qH-4GXukuJ%1S(3UuBk)~pj`U~o8ho1cNfy>NxC
zY<4mOLqpegc?Jf)g|=r-gfcTQfQJulm*4nY1R6UKs;l8-Sn%XSmE^UP3=9nCKYU|m
zaB!=R=v>Xo!0>_RCnLjxhg+&_*J&~^99aMJqbfr~y5*9%d8Wpoft1SMj0_JnZyn}~
zNo8PYm=6l|y7Mc)*u{WGHsnF$KXoT7zvRUfGB7k82SwrjhbmS6>#P|V4m5+jCtu9A
z*En3Bf#HE5C>+mQ)E<*zU|{$G8Y2C`d~R-Ksu}|WLyd1814G3W;q-e(ph@3-put|7
zBaz1MXNoc~Fw6&8v+wzondfInGcYj7gB-E%Va?3-GZjJOy&zlT3pbrnJ|oP)(6Apg
zj4;1w*_p>@#26SFwu2neZ|VDN`58&jXaq>Hd_mut_cJUR7#P-rWcOP-K9hU~8aC>N
zj@v!~3IBh5v2<R#7$XA%$i)ATugvJ$$-=;p<5$PP@T2{6QdF7<XkZL63dg{puP+z!
zT;iE11H%U0pNtF#Bn{b(b~7+E*q-EPIPh)`U$IFs4+F!E2~cZ}JYi=@$d>bdE|Vt3
zz_3C3CnLj+>B5QUQuZ-2Fhqkq&A<Q|Ud=hR_{E&_YnT}rzA4%>FjyCHoe4c-%fOHz
zj5M6s@V4U5oa~v63=9YOkjIFtKR&QjHsEJuXm|>8hufT=MtqwE85kmFBfCRf&Me*J
znF<5L1_LB79T2lgJ2&Hu4+BF&D6&;wD-X<>ICDM&!+}Z2R&{^QuzYOn&B)O36%=T&
z23y#(g+*zJ>zEiAx{-YaYRrJcAhPak+s+vq85j<DA)A){Nx{<CD4&s`Ar;v)u_uB>
z3=9lAKuL&!S@1jqLxU-@eAwfMg=y)0%nS_NpqvZ~L%404bz9p^XPjhUIPeD9Hjq51
zpB>SDe>EcmLxUs8OamoLUIvC4vyegxqz*h2*ZslUbj|TKYzz#~RKb%III7~X2kM_9
zr|#rsVDLd2{sb9=y;qY^^)El}T3Q=31A{RrsiS)Uq!a7_5Ci055RK9hdRDgk?z(>*
z1s0!W7#L>sVRJl44_3V(2`Vi+FxYteZP{0MkcoDn94);2{`>HH76t}}2h2!`2_#RQ
zNd%Bd4EUFt9Jm7>@Mq*ppU2F=a2Z>21et<Ae3zAjrzQ#%j6vZ$k(ls3!1d?;o;9cL
zurV;G;Y}@K57j?K_DAwEFq}aes0X<Tl3Eg6>MA**Npj8MLR|(11|BEGs5)F>!_psr
zRj(zeF*7i1233COsVKp;Zfo1knTHt|4lp5Sg98qGelajGtZ}SkU=Vx4AkM(RunyV5
z5tGFgW=yQ)W?;~9MzVH;4*w)$abqzChKNpV;i3IG+w9Dt7*+-bF=eF85;3R!l;r$K
zE(V4*?#QOu^-nW4`Yg=A5HShKv;=NBgLI!XH3o(aTF8Zzo=w`hj5D4L3<-%y>8hc(
z;>Mi98NCb)2X28%TK#i1l8u!d3=BH{$X3bn&nwn77GPkw(THr7yPW-Vt!Hu!3>!E>
z<?@u^gmdZF7#SFTBbO;}PA`5j=VT2t1H(2Ydj^K+Vx=>dXG}noeaP;(Td6a5@yuif
zh68P&kY0XR=ENH&28M4cpo!wZE$j>o3DKa+@pN}`5(5K+2dIwvAE1yiGY~Wb39gF@
z<9v?BFflNgsoOI!{E=UN%;vlf69WUXTRxcgulvmNnVo^*fh(wrnjoA~cl-<^149KU
z`fAQt8ri3U<`@5flGTqXms8}@w=pm<>;cOjooUo>;LpIo@DJpVn!_iJ;*Fgd7#Qw>
zlFq*8HON)3+@mQozn|e^U}!iGDkA%fuAPZ~#>~KQKpf;$`GQAhw2c`V7#?JU{B+);
z9I3)j_M2b+>=iQugAFLj{@_i&P+fGFk%2)D6cm3ZO@48A$0G&?hJKK(b>}O;AT=}Q
zJqoE}UuOhrlibZ&%D^DB{r1~e{SN1|BpDbUl!F>a7Yh9L%3T*>V0dsH<dB}rucq#p
z1#0ksLdomg8u5bt_ha1|7#h?;0c_ZQJ-8U$JOVjWaZb{CNYm*~&PE0XzEW@jT62Dt
z1Ovl@r=VtAvgLKT`PnQC3==+oV`ezuxrfbAp*xX*p`p0~)I?J8+vWbai-Cbb<~XQj
zmi}4l$kR2Aj0_BYpn1y}=awBUSM?bf4p{#AA;fUNbWZbp@U-BZV<6SypQVm)>Qpf@
zF!+H~^EkFxbUX#MHdR3$Y3vYC<c?)vXy699`>>$myp&FE(B#igMuvm{r6c+gcbK4s
zfW%zBkGk1W3=9nyK~YmIplFw3%FV!FpaxQ_rgUWgnq)=>1~-r`KAE@q5`S_rFc`3c
zB=csMaI6kvU})G0(%Buc$vI*T6ST^TxNt@D5R)haLjofxupTY*5ENU=0Ikix8F}<>
z-~u(#Xa8YfIIz+8P?InNLxM9X2iO<yj&x>XVEE7rS|7o{ptjhSfq~%zsBr`;s8A{`
zkN}k`9*|L^1BRmmhOqW0C_RiOt<l-U(b+^$P8eNEIXYknN(Z2>H;BgH*8!;*EjveW
z+4<rAw|5%b3zaz*JkUDvcm0|g3l0_wvy{(gCmddBb-*d7;l?|gOy<!-WwcNM6&0g}
z3S`7~G%P?NfF~?A?mz#J!QkZMj~4&hZRVeUTn}0h`2E2pmWF(rKdQ%jRl6UA@3CfJ
zVAw5LmG-YNlc_-e6LYz7mH40dd&&$94bsJ#Ob7H&@ZUM2x%)wSoCX6!!|j4hrUQbX
zm{0FMVfEuwHY)?e29xP(3^MBW8&+|@YnorVAG8_Z(Iu9K34ab$O^aZUuRP7bz@T?-
zDJO&F&&H`b+xhl=TF1!15HrDBn1Su*>o@!i@1v@e|7`yEoSlJT$IRo8H~w0>?bmbm
z2lxK`YGl2WGxyUaMh1pCAOjYk<d3;^_S(VlI9mpWhTt70j0t@Ie+XSKecb!u{N4F{
z3=9uuy{qlM`}-wBMBkqSu5ULOzx~j|z`!70*!=(UVe7IAH-@l>^6`&~%wneQX=7ku
zaNcRcm|(ZR?m?8<9ghEReqCW;U?_f5S^W0r6^59uKL=Xh?2&%^=M4h`!{awKxgb_d
z<DUbeH@bX4%PgOsGh$@$Q?W1L{I-z)83O}DKw)C70XxGvCHn%q*%!1gGk`V(<bFM6
z!eG(*=fKG~4)bSnGB6wvT(|1{8J32hPuS0;{QlVmnlbv*SN%#`jrl;zC+6iFzt^0v
zVPIgWJEi*7_A_IG+Rw(~8x{8wy+AWD#m;*VPhpthR`-CVZ0>i^+|2>&82|Ui+6>Po
z$j>-C?Q^giXlbu)`DOo^5)8s8_<d6MgLWJ|y~NUxJxM-+aaty5NxGgdgWF{J8OPI#
zTV66UFw{H?vpV#JLBgvpLCE@SVH#+S@u{gLb0nDzkcPI?KBRVac``9D)D*~v`Uo{R
zf`-}{5)A)!TQbDV|8t;V+M#KcObiSciZYoDn*JP!Fq<LhBg(*VW9IA(mS9!|(7+lf
z$r}D_Y^*6wlGzMeG5thJ>Ua)g258&`(w9sSiJv8LwuO<Q;qH!RH{(PGC(tkl0|RJm
zR^rfgRR#uz3{bS`eqz=+^NE*%!Qu2$P6yC<9LVgXPt3OQQ)Zmp!pP7dyQ4PED3?J9
zp&z6Ilwlms=$kw@E@ohOa4*L8^Gr(y@Vpwtey|$Q%2?I?XIVf)Q<qp8Tu<^BuwN^L
zh8!QBDT4_g`<>>U{=>-7@VoHkoYQ|8EkMI?ATz1k!ppFc>)&h-S|z<5l-rh`<Tsgj
z{`pOL(6mZ)VJ6doOW??%c8%G1=JQXR-^w{>iS=RmgZYo4q4+@IXXB)+EDQ_{)4YWl
z#6W|hpm0H&B02I$tIW=roq^%q*{jC$XEGPeK^iUwsZ~(3zwnv+>`WhN&{*>AbhXQD
z3ZU6KkeuO9MzLqynxO3+F|!y#p0KxVSi=BGj0d6+fnm_KerZqIAqIv6d3PKa&op3A
zL=1EDJn<HOJVTd(VT1bh3l?c8>-dv@zB<COjEjNc%^6>lrj?-GDG7#VPS7ObHbGwE
z9B2+1lo%PVtJ@ni@7<6z2{e^@$6a(XOM(Ex7N19_MUI2!RS#%~Un)%FIAHOK`SXp;
zJ_AsxcK(i+`wTe-=ac*!7^FdSue#IK7#5%8_etG}l#OScjr)O~(dQhP_StSTXt{p-
z>zB1@tOsO1F+bn%de7l0ph4#6ZB^}>j0U}b4rJ!o+&7j7%`_Kz)}F6nnBiIXz~|e%
z^)q-F7!JJOv3y^W5rdDKeSy*K^XX|!3=9P=t6v!#GbY&mZ2Ww)F>WSk{eEHI>hNWZ
z2Q;6s>m5}4au77#tfjYx{~5!9$S3UU4%wxE5~gnXG){&BrJs%5H!HPo{k+M@z;Nv5
z&s!kY4yK=t**A;LZ+%|L$iVRI#^+}s)((-Mji+zsI^TL*2@<{i>Qj~7{AgQ!hUs5F
zhzm{sT48hUA4hWKZw3YiHBi-LQup^j>D}t|UEeQ*YLv@+^EX!8%QBq)_?lg;V6*=6
zikA!w41Uiqu{2zK!hWrwfA59YYzzzqvU<MYl1|loecL@#(4cQoCes0hPt30)^Gv@?
z0~s~P8@vT=bySk+mpVoU2Av~IIT;jxHg1hAGyReV5_mOh`Z8nThNqy~(RG`%z6b-u
zf!rM?j1M?|Htx1ewf-W<$iQ%ChPN<7onzgDZE88~aiB0?3sO@1iFvn2nag`_1_p-z
zpuB4Sg#E|$#}7+EmCBP#ED7oV#6VMc3=B#2b75=ucat}d2Fe-KEqOpDg33@ZjejN(
zq-1n+@#y+`P&z;==0V&M+}mdu?Z{KRSu(m(6*S!l%2&i^vm5putBTf!6rBTgdKf%i
L{an^LB{Ts5jYymu

literal 0
HcmV?d00001

diff --git a/serialstep/board/hello.DRV8428-D11C-NEMA17.interior.png b/serialstep/board/hello.DRV8428-D11C-NEMA17.interior.png
new file mode 100644
index 0000000000000000000000000000000000000000..615ca64cd4bbb7ae0abab441e7d59aea3d0db85c
GIT binary patch
literal 16144
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

literal 0
HcmV?d00001

diff --git a/serialstep/board/hello.DRV8428-D11C-NEMA17.png b/serialstep/board/hello.DRV8428-D11C-NEMA17.png
new file mode 100644
index 0000000000000000000000000000000000000000..bf68cd92c2cb19c62b5c346f26a51ca9eda37af0
GIT binary patch
literal 84778
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%0A>U>%;1M
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

literal 0
HcmV?d00001

diff --git a/serialstep/board/hello.DRV8428-D11C-NEMA17.traces.png b/serialstep/board/hello.DRV8428-D11C-NEMA17.traces.png
new file mode 100644
index 0000000000000000000000000000000000000000..505d3283c21e9e5547b59789b4347c63a6c296e1
GIT binary patch
literal 23877
zcmeAS@N?(olHy`uVBq!ia0y~y;Lv1XV7tn}#=yWJtjznGfq{Xuz$3Dlfnnw;5N3Ql
zafuQGg93x6i(^Q|oHuu)r`<N&?HZ`H_}Bf^dF=nK{NC((;gpxqT)fTUv9Oj>gXphq
zxwrQ*GC;tbH}fybLzoN<JJ=>NLD>R|K~NThk_*T+Af7{u2TWgwfF?);gawsYK@<Z6
zgM!l%D2u_RLj=lf;21R&5)`9h3JC{>(IhpRqrgdFv_KgxPr(Ucv^oI?0|NuYXl)7&
z3FO8^P0v3Dh69%0YUTe5GB7MS^|nkJ#9)|KetX+lUN#0DmpKd!4DSWC85kJm9Jl|@
zz`!l2!N73fw@o-RNMyDMLjogTAS1&AnR}}k7#Iq4@`D%}ikMg#7%cjq=Q1!fBzKB1
zESSL@47Pkhrw1d07pDjVgTmp><_ru63SGDu0!}DuGBBi6vavHTShRUCGMuuIfi!%g
zKzchI7#SFjeYD|YVEAA+k%?hSfdZtE-y*EZ;K0}jX;^Jwn#jc9<F^284Z|8xdr4SW
z1H#i5)MPlYgoTTN!9f1}OR#@584k3_)G#p|n3K2t_KSW728ICNB@7IcL7oF?S}ml>
zaKHtmg@J+Lz$q6l1_Mr*O;#YA9H2JEG<q;Huz_rHXuti|?3XeF1H%<zO@;#wpfF%y
zV0hpK(hT-QRYf-w1H%DBkU#^-S5+LKwp^cb5JQ6j)bxT-B~}IwAq@rw2l4zs1_lO;
zYsX*kGcbfJ1~4!*$US0VU}z|=n9Rh$0@Ayn9c0V{8zoi-i<uxM$U^anObl~8pzix{
z8?1eG7MIALb7Bk)S50jDnHd;jI?Xj14sg!mb76%9rbCwpBLkmW0Lb$U3_s?8cq%a7
zED%o##+wJ?DZqF$Js278!BkfCfOs&u3XmyraJfDYMus@J9LSV;aJgO&MuvHCxw#&U
z403R}eh?2XH{XMip$^6aCzpMopaHqt0%XHJxZE@kMg}{$9LT<ZaJhC5MuvZ`&@d{P
z*AHr{rzr;PXj}GPl40G6Vm<~2hBcrR5q<sW*5=>WO=^!b6r_H?pL5=Zfq`Lz+W$Mu
z4AZZdRKDHt&(!z6A;X96`}qtE3=xyfH5m#recSIdwLUkk-Oq5~{+>`!O?2(CFBd~h
z*k#sj%|9U$-~X&*W?(pA<-)}f6Li^eJ2dtpT0IyWP77+RS^v_SjY015cUcAohHDBz
z3=e{4@oi`2TA%r=kFnwTkGbp&3=MTktPFaKUj{@&J+j7Q3Bv(Z4v}>WUskg*#6A8l
z$H2g_t5bv_BJQ%|Hkb`FJs2C7g7P3J%$_L*F(gDn(`v)c4iSckNl=9ec1o-a)0CkR
zJ!3K`p~Lb=xN;Cff~IbMpa3+Fg{uTHBuK)|=@em5fF;2gkcFxydt4o%&Wr)YFB3F#
zF@VzUT&R@~P}A;g4@L$*c)HUErE6He`(Qqii9yB(YT^e=5D#YI2U8Hw1tw<;;=%P9
zPh?`);|Y_S0gm}uoFW_87<O!`z3*Pn!oa|=pvQc)69!5hB-NT94Sz8+FfbS_2L)rx
zLU6%au<P3UA06jyZ-2l2D^@0R+xsUO;s5%=|K~9>G&~0tV-Q=AJ8*xB`56wxulu8Q
zE8X<msn=!CFYRcn=-Y1zQu*WTY*2{_Vh;M=FSu%DV9>t(z4nVcgWbb?;i6mr?tw#v
zfq}vMvl_ULYxsZj`(C{@3=9owklucSJ%=a*!vh&8&%a_d69a>cKcxTvfp;N@=MLd9
zFu+Fx>K^2BF)$SHKt==(Ft>0)YfDg2F)+Zww_?I}O$LSo)zE<le*rB9h6AsmJO&0>
zui=5`y=4px4C@6UxnPgO3I+y-^TH4wqAArNUOAhIfx!mTIrqTM`CtKc&TO!ABp^Hn
zgmWw!z|J`jbpX2{$T{DkJS68hfSnVM>40Xi18V#r;ZeW@3Y|ZoVjJRZ*jS0*BT(pk
zh*x4|cxCwkR30-hy!Zf0t_Q4HxERj7E8E@sk3;{n_32Y-zi)r}e(aRnzrANaZQuI-
zcgg>|j0_EddpsE%qBhHzF)}b5@PCuY$N(;>rpmlyU|{$loUhNo(D1WEgkgnpfW`Em
zObiU#Gc`jt+-G87n8?JCD)VB_=^91`hI6U+Ss4yo?G#~HVR+l|oX>yrbAoBJ^%)or
z1cu$-&&c2aDw{-O7R*n-U;deufnl0?@QMU}HiiRJJ4F~~%sV{$^9)_E$0mRZ+bq3{
z=aaWFFdVpA0g8nl^&p0XD88I?ATfr=H)k_46u2s}GAuLs?ReJb|M#<-)8^|kFdUdU
z>w7T+1Gu?#xv;ZNZZj(b!wl_^4gSmw53*di7<`sKEJ#~+cul&=88HTi2VHNjGcfEB
zn#ja(xj>^Btoq0LYYegs47WgzayqSA^;j|NbPgi}!@4u~co`a23urPJ#GH2Q0Tt;9
zy1l<`7#K3XgTlHXS9ki0UiNU^&3m)w7|JXxeB1x)z4zla3=Kc;=55dX=Kp(N^)p6>
zgvxtM7!DY0mSOt4<YU8%)NQxFW$)`XW@BKmaK2o}$G{K=s<Jw!IZr=!`t!7#dC|{n
z7#SMA-k8n6;BYSY_O^Mmc^IZ$DC)dd;c?aIcJAvr`X9RM-!V3@z5f&U^X$%bGrxsg
zQ)FOR{Yj0LVNsgZho63r69Z1?Y+qZvkAZ=~)3@4&fuW+!gRx=8H0Ei?xWB-y$lego
z$k6b)Q-q--W2Z~L&4jF(Z?~166K7yZn6m7z90P-m*Aj*UFQfQEZ|Pn5Ub}wg+ihRZ
ziZd|mP^%VaV6d3(!PpSIHD=LvS*NXMzOKvN$G~u4>)9>snYaHlG92)C;bNGx?5RTP
zvct>Ww?O3?HfP>uXJR-|4w78-lws*xroE}_%5y=9W5?$Cj0_FM9U=@CF{fRtZZ`&>
zj(LCU88-vNhvhTBndVkIF);k-@?dOm-YPTeOv!~W9n*H++X`~e0>|6;1Q;0Xl!F)^
z80faE=8C`2E#8|APKf1i3K<w4L@2Q`@LepLc&}{76{G9Bw}DdhmdxAgObiF+yKph=
zS^KnM36fJPru^k&V32WN!f+ruO7GHbz9~`9s;-;GGcYuypWX64^R_V)!-4&sA`BIg
zrx%{^VfXCMnE5*PHYiJkUD#I6!q8wnk%>V+(~>81w?jTm>Ruv03j@P@VNHe)Tc&k?
z*>-sGw4Hgk*WcU*^1}lT<F~D|zD;CcC{Pb#c%Z4vu3#)HWxFVK-R*1U(cnyyAg9F2
zAa@Pqi_UvS*K=Rb1|@&Vv|G}qZ#5Yi5^lS2G1#nldLemP^CI^xXG(AXO5<i=C=m6n
z_GVxZ&}8_qc-rB<ZQfs|?aYh54@%$X(&n=;Fs%P6@t3jTylHG)+`*~*a#7ckZkJzy
z8SilFZQ1O!`t9#`|CMH75CxSQ`e%zSe44z>c}DI1>}R`jV?p_C$F606)fgDAs|GPV
z2-ann_MQGh*LZLCERX{=zWFgQe2|&Q#898P(<k4GBWvc%*vlaM-DYR<U)}bfh2cS!
z3m3y5_tS~TeApfAGhy-!3=MiptPKC+Pp4L0R;@bi^L`e{M+TE;ehbd64rE|h=emU9
zz_wglb_rwIUw@XQE-Uv1x#mH2Zgmg?!#d|B3=U@xx*}`UuGVH?_%YLi@xh}gz00%t
zs-n`WuA4+NFf`meyXAP+?fFa$1-$Z$?HL#zZ;=T*Q*z+*<Y_bSnVy}tXWQ2^zt(s%
zG(3O%JMTR^!-0^z+uJN(RyQ>VHmq6JJZ0Pcj%7EC_HFyh%}}6r{*=r?W3vxj`yCl#
z8qGCrPAp?mSf3eu?VI&Qljw6-x0Nw6FeIdYuidp-nj!3&FPD8m0l$IUWw$kNw=c@v
zHfMS6T_%Plm3hxN=Iw4Q|7pvV;HuP`f5U~L=i-*1S-;k1%+h|I6}6p#VR2>Ov)Fn2
z8_R#{G9{S)@A=2Dc~d2W#Ny1$SHDDGGzmX<bxR&2L)wF%oDCQMh%s)Ens`Y4&jaS3
zizO59At^`@{g!e-@Xbrch)$1({B<uFk7ZbG$pqWOz;I?&CjWssZ_YL-|FC6B5LIfe
z|Huq-Y@+YweAmk{mhqQwu`<k<_*|1A?ZJ1B2GI@?28mTKmG))|-!KV3cYRA4BSS*y
zw@e0x58WP&4T({F8Q*Hx?|PCuQ(MwETbv=GY~ET128Mg;K|kbY`!uWpWsLjn({@g}
zxUG(nA))kJ&H=$U-x)L1gBTRnJq=ivd-%FhI0Hk2_U3YCh6k@)xENfv${gbm$+*6)
z4O|a`XC@4F#b4%5->qA$x;&Scnc=|I8^;+L3R0C=8I+><5^m|0M?drOyDi1Wkny;(
zd-09)j11szs^9gZ50}br+%O6+x^>Nf!9n@_Lulu^VAV9{J=;#-owk#Sf#HK`wKW67
zI#AyvGm0;og=@`%Tv<>{k)gm>iIu?*T+nR1Z4|!g)-^*0h7YrA<ro-19gGJBy6if+
z;vjde2J5Kbe4m-&ftQ_IJp;qFOGO(lm2A9i6#Qw{HA992TsE_r85s7QpDn^*;d8n%
z_VUrZ(>{z03>E!<<w4!&AchA5y6u`wtYH_oOk-pSd+>7(%WEEn25nGQ-!{#8$};b}
z(`FjEU5;X7h-iFX%)rp_xI=`Y!uxb$?B%6-r+p+BXX-LDFr444&ccvTs>I3=cde-4
zQpw8OM#0B2qE0g~tp3n*j^mmv1A{iG%$hWfc{12YCWZr|ck;~7zu-yz%gC@nYa$ba
zf3}6j&F`@b4g}4*X3XGVeg65GLs2XY39jI*WE;ijeoL=7`q?Rq+-xa^1yj?D(@Nr}
ze`93;k82#*ev9wrExz1a&%EPq&thZ9cwjll?SI_%Z=4JaCc>ILX~Ad0bIhJU%HQgI
z`+jffQUA2K%h&W77<wL8$~-gtd{34k?dy5akb-;0Z2_x*MKiy0gUZVTt6jJlt_W*v
zSQL4ED^$qZg^M9%_E)9v+Ikh0F1L4qrpg!^+(8YPt7Q|l10Dz(ug}hw0BLV12Z@?|
zc72x~^X^l}%<EfCc|hU^1VP5m{HgTaSg$-Yofi`CA`_VyLRq-hWL?_|N^qcoqb1;;
zn4IZr)pzMJZ$9-b+sX^l&+z_(8Y_dAN$evok&0tyvTsL$9q}OJ-V%n%MTRW<&(?JQ
zR<GY}ll*LJE+~E&7z)_(gBTLBjN>2uJGoSE^@eHSgl+-KPnnz|5jWSoh8f}mZXdm7
zeU~2d>eHHKUm-TS3u!VK%w5JE)5vswR%LDUd9XX?yiNYX&d{)XrhdNtW2foqXZIXi
zn+}!{0u}R`XKE^cON#GWbEFFFKm|})TfoG+F5y~fo-Nqd;8xp;Nd3J1kDR85Z&_Om
z)(v)7;w`;AR<1os&r0)rA!^lv7!o>W>gU-%HkuxOX3x2`nPAm!0-6j0=AVzgO^<oD
zNh(_kB-juL%GR7BJGvsT?=l7Z;edw{D??J+-YtK-PRGPu-F6Ke1Rys#xZGa4)}b-{
z?4E0Dvq8EU+=Mk53U<xZ&$WN7G#yDi4ctK9ux+M(?*Au3(?cU~gO#5-1j=E(4vpF~
zOZP@Y#axy!9MDYLyWww-cMMon1E?p`F04^tx_MpYYiW>J!%a|I<;t4rTjv)xo<6lE
zpP}J@^80(+ZeN*X(Bs7R{{N{juG_5Gt+!2xs9$?{&UV{ddT(!V9A3@@8u#iHVc5~@
z!1(LIbBI}SvR9cI4E9ZY)RJ4wJbmZSpWr}WkZz{Q@IeeZl*VvgNR#1%Q6tlruhkFI
zWx#H@2Wo|Q`kSZCfA~yy^JinwI1j@C4$vTsT0q0TACl}KWeFmnffYdwhxk7|;OH;_
zHGus=qkJIg4}73JEU4j7|7Q+FT52K_!+jwn0i}sd4DmwHv5^AMsK$TTc-8|yB~}JI
zRp_wFgFN@I3=Ch=mpC|rMp{ArXTI4Y3_qGd&1VJ%hK4XuT|Xbjo94pBkaHV0Ot%0u
zv;iG+0Z;vP!<;ywD1@KEp%)ZBFrhOC)L0u>VdFk46oMEcz-@GpC0a_X4XvO7MUeMa
zs01-Yw7_i4Qetgjg-N|=^k7T?kM4pLRw)KC%$NaFIIly5K@H}u1?Ebu4V*B`UR(^c
zW%#i3VxH0A)v#fo*Bd+;8;qciZ`gWc34_BN3ve=JNboh&WDtNE6#;5EOF-lFz%5W(
zhdD<;li|V~nEkoJnhY1<u3?|Z#Bdg-?#JCgTLy;DR_8ZYvFHg+W9T{mTc3epZ_!;w
zh8t$HMHm|H@7Ty{u<o;s>~Thh7qg1PAg#j#@i96K68*{M3=GeDN)N-<0w@>$<6_7L
zcSd>6u*QKx!c8fNfx)ieFn0n^-*pCto>Mz@7}j`$dZh*m;-w&8Nlf$rwPFk)9(Gd&
zEdr1Lj|ww1Oq9LKd|?{*3<d@R{^#F8=Joh3F;EoOV`NCMJNFr+eMX~4qLN+|Xux{T
zYfzdq;GTF$C1wi?!w>W4UTd=Mf4}tp|IPPtUws%Dwmf~W&+xz+G=R{+8G4K%K6Xak
zpZp}ya6^OX-xYEV-!+3785-_$f^1@VF%|4ErK^pHHVbaO0V+`veC56~Fq9nTUH!cG
z$Ng2mj%lu0@aucdkz`?zjz}}mIDijiKn<LA7#NyY^MS`@9z-g!GCW{5-_3CB;$g$z
zQ+2s)&wvUf2hiy2kLKBK43A$toS_R&`wzH4;{gX6s&-ub?*$%@J8-M-6(fV&g~PrK
z3~|pb_`X-027LI<0UB@x#S#NU2V}G{Ve+9zF)DASU){;T@a5Ii;?VkPki$0Qf?Zb7
zI71ASrpv(#B`Qv>Zfw#8k8#^n+yRB$*(FS@(sB$9Gdt}V8)kwP{kWzr=<q0Mmjxq3
z#KFgN+}AKLoH_6qG<f<0G#I*o|6DyogCs<$y7(bbgzNwfhcYzy@0HTHv50};Lf>Zv
zhJ+GOm^0)-hD;x5gL!rpsw^ImMBf7*nK&R{#V3*z2y(FmXn>QU;lD7*M1~8KKrzvf
zdpnLFD*qr7R5+|TdX{xTQ!@XS$z0$-p3&^V*uY`V!I)ro(&6E&oh=ni3=+NB>I?_8
zY~C?8Jo__|mtoK0ouGlt12*8nl$dLumo?2x2l+l?t_NeovYJnV49_lqP6m0A;l*uG
z?zEi$kBMP{``-D>zuAG-tsHoj14^S0G+#12cqPUP&VLU7UAP!bo~D7F%fP@7_Tau$
z(5wanLpeA%&SqmUFnj+L<hwghSI99mnA+s!#rzFXVF*~R<+s5Vq%|Q<iIri|9hV2%
zN@7ukZyF0L^g-%p%sy@lD*to@g+P-o5n!j69E3RXnL5ZdAZ6f!j)7syW{6q5pdeyk
zFz8xs$jT7leS?GHf;=c;F)Vevu}Hy>p~2Ah-r=KM3=Dri>;M(+KbjmE8IC>wE5oor
z9_;>8JrGwl{02v`hT$P~DfbzI3>AIfOBovMz=9G^RozX}k|689gEPLsb3=X*FIxzd
z84kol;xoe;l;s_!K+@Z5h+IBY?)eJ22Fo2C><0Yv!&2SOg(k$@n+`JKnNrY$Ts_dx
z>E;g_TnrNZuO~AwB!Aq&e(w>;iUm_k7#_R_)p`xzT)6g}VYOjkSTI%4Or*yEG}q*i
z4-O`s^N?UN0`p2-K?XAzfJV$27`!1Nr2rnLb1(;`3kHT_us1g7M1zymCQ!y>U|8_z
z+5fBH^0eW5r%1<#Ol5`zlZpi&@b#&J41E6?9D>u5!4dAj3l8R*!(!l)r5YSi5vQ)|
za)HY@XmEn`L5FHjL&AB%HBe#9z@QStE27nFqRmh&^oo(;0%-n;fx#}Yu-I)5gM+@@
zdrwe__3l|AC=h(|TW0@PKErXKYL7i5Ljh>)pMl}e(dBNS<a7(XV#;9a>iG;`XRtH;
znEYLnf#IDBD7`c|<^2J<05k*0z+kXea2vQvUgH9arvp>mZUh({>H#Szhs0GH#Ak;B
zZ5j3)THecWtFXCE(z2YP>d6gIu&wb}a=;+w05bzal;BH{)hQh!5}@?Nkg-%LV8<`>
zz7D1av6y0Jh6RWEUx5@PsOE8iXl-H53%24PK=nDoQc(MZfx)5UIA~6ZVKpR1R6xoZ
zzy&4)0}~|efIYZjK?y^FDY)pI0WPx}miBB|n9w2#(f}G0V_-;-6gB^!3ocrIfHL2^
zCzstA4y4afW>79X!^FVAkd`(XM41$oc7vVGFatCd0}238;R;I14$P1ss)2;x>{woK
z0to}JT5CvxNUpY61<FbdGkdnUCN7C&bW^lpW@uR72~xTs;OJSMLM8|6{^T_gj0_BR
z&%rTRFnP84e^xGr&qaG!85+)ml_m)0%>X(6Dmc*=G=pMif+`;~Lqk7U<ij$-Jf~i8
zGB>aXC$^TQ+cm(IdP5vIxjo<od559lIoLdf6X2wnkm~-G;exXG$A+m(^XE7;eJ@)e
z4o;E@rDmE3;$x10%0UJOhK$2%tUr1|$vq>rMVHG=i_zw|sR{!_#av%dePJL8F7qyE
zPh|Sz&dATeutf<RP(M6DiHCu=@(jqF1Nz`XWCo<Y^a2u`Qi5QWe;_J_A?aQMG*isL
zAmzcv0C9~7wB+J8{|5?%eQH4s;yXTYFeHDx$9v`s#49SGnwWv18Pb$o3>}b%55Y@J
z02eg}I>6y&0BI!|fV!Aq2SCUD8yZ1X6azz#57_0+kXm#xIK6?@L6$~HG(ZgF0ULI~
z66}2gZg9YZltCsD8v1T70`bm(^AN*ah|4x3xy=15!-1N(pIgK)@Xz13MD#ts&0#~1
zx{cuCdd5T##vQ%0{TUAImU}Low`G%6;~~?3VvUw-YGjxh8m59{wL!5{I6*JTm4PAR
zaQ`dD2Fo2591M3(?qt>8?E28MPuM_z|9u7q14t=Q;skCxoPo>%@El#fCb6#WJR<|R
zl3`$Y0reCY$WspGcPdg%A)zk{inj&Yd3!)9=)fMZv^fjc8fY3)1^J>XCV(|!@?-l0
z?hrku;06ZB_Y8tyrUPTNh|wSO=6!pL-Y_#TJWB#+uNF>FMra5HCrXfNXaUFq3Ar_p
zXi$Wh2^vWNsev!@WQ61~a7ZkGM8W}okYmBBpo=$nAx41)i5M6dq#)C>(DVjU2buX;
zzz8Yc?W|U@GbHG)k6FWBF+G{zfC(J6;5h)nJONMuFfcqQ<YzEZ4`5*UF$<Cmv_L_^
z5CEA}1(lc%!4Q`*Fnmw|7p_VW{%UaCLsw#K0QG!)cm4o(tQZb7gPJr9hgv{=n**yr
zwakqB``+KKoOd;ufuRI6A$*`KMxLeW;rmZjpy4LD{9peh7#YHzDuJ4P4IYdQ2I9|u
zc6GFd$$;B<48J}st^#=wgcEoX!E)#^xGlrL!1ie3OopB_kl8h~rLz@xm`k#rmBuRX
z+g5vjwL8cR28M=*H^JEg#DfGIhy{%@5EGK_K`dy~1H^<)l`+5yPLLo2BqM>C3XedI
zpKa$puaRp!_~v(<Ez_NI8w+Im96^!>=Cef@)SfMqVOad}9;o&NSI0i5eB~J2p4#$&
zlsr=nVwf>uwlzb~xoSxU1_P%4HOvi|Gj$;A!G&?f1|>+L^9)?XUy!{BYD6)dffPXu
z3?Gyxnli*Z29?DQ<}r7gE$2SBJo<g!Q;E=@?+dp_{_|yEU<gwRVu+a2U3GvfO8)h_
zJ8uf_faZqI?|UEI+Q4vO61a5+avR*64|Jbb#@$o-aO(f^bhGD-2a3T-hJoRL_d5>W
z7A}SjV$i~);O5-IgFexsEnE!X$$5||1)i%HBrFSXT*JUHUl>&NFfcIq&sJ6O5YT2g
z;0`Gp85kJ&pI7>oC;#7kUHKbB0%&mzNbdv9mC~<`+qmjy|NZ*ccM9WyW-N}2e(8Vc
z_Y+%07%(un$Xo>#+MrhEc5n(<APmmOAT!~<g6BjAhMJc)=U)jjG<ZVw9ayz0@7LYG
zF(1U%Kc2b%W$B)Ow$Zg`@5Or`eLdspb1sGldU%aP%-1q7P@KR(OPs*&hED?HG_>y(
zW5fBkphO7Ka9}OCZ4c&<w+I~;9@?M;&d9*f&`qg{;PMXSB2oedlJu`t&bta~3o|e<
z<Ztj~WPmiu7#J9ifjSMlK!qBpLud)=|6MQzm3{v=y|4btkzc%zn}K1?F|1_;ntNK#
ze7KVXb{?c(31)VH%c2=`c|q+31_t|15r&4$9fIHt%uowyErS$73vCdSiX{xz1ORao
z$fjpy^U}X^IGot`{;Ki?ORVcA9)gMk28Mu?X`wsf+~d<KWpA4u&z||vH0QR>dS-?d
z>EP-NWEd%BAgJbi4oVk|_rV1pNIwGu&v~rD42lzw0*4Owzf2oIOY6YA<VP$FKTg8R
zbSWVX253WzfuX^Tg^S^XI<#a#EGA&cI3UK#@WX>vg*n5E>!5TNbLsG&-}}P*85r(<
z{C7kAKd9OX0rwsl7#K>@wr$wZ&Oe>u0{cX!JqJ#L+5w=xY^goC!3^>mcrh24LF#IK
z&`OaiP&WjWm{+1SF8&-d16Lyq3=L&2Tpy;_-Usz~!M5<qTxE7xzskAwvyJzDd$7=*
zrN3rbGyDZ*6)>M+s4o%*)wMtFfD$^yKMZ$HArjjm2vgx5xF~06V1hIn6x={<l5A)u
zRRFglA$h*x8EClXz&1n(3qTUv1#rh6+NJ^7M0B`Wfy*0)3!vqZAdN_khLS^KtPE+O
zf(j(@qQQZ&K@?iLGBB+1nZs}Zw1AX>fx%(>ogK^!4Le~uhJisK5tcuF=RS|LWfDjd
z7Q4UE6V#ainMJhgs9G1n+}`sF65a_KknnEkKElbs@Ik5{(vI5!9zR?Ut@v%g3-aEB
z8<HTW!|LJ&b#TuGv<Lt!OwxKZaF-RV4SO92t~`Ei1=R##RR>(4&6nQJ1C3X~A<8fp
zGH3*nS2(1``eMqeE&6tEL0r&G=Vls*HQ0q9%M$XyMUI0y_F5L&_|X9;@q|pdR(PUe
z=oV6UkeA!voy5uz25RDiOydU6RKziXI{={KDd`SJYu(SkED2?hxI$_+ZxEP&sqNoS
zTh@d$gd8Zpy<4IOEplE=2ltmjCKGHGW396|CNkZ<{e3U2Y-7kP2muZHFfbgDs9C_V
z&Jr|i&+wwpmy741Jfs9;V0bL7Y0!gI%rSr7!QQsnYefPtcsi1S!9W_R$^$bSmZjYk
zF+ZKQKk}dLw%mF3!VC-zQ*Y3sy1?a2P!J(4e`6rE27u}Zw_@ibg;+y030)XaCyarC
zAtCg6<+PgnwfFP?R_Vqc50Ah7ddI)LQT1;p#+?p-S0ih@r!9B(^HK(euh`QZxMK%$
z5D~@95BciyEw{IAYzqvjKlr`=sipbyjHoSsNuJdnS!-Xb{nA-f;FHS_Ew>a9`Bn&#
z<Om5Ke+Sim=XO-~cb10Zk3UwNIrENF{=6roamK*lfQS|qXijHfaCmeBH0TVfQujw^
zzn#axkpEBxny?v=odOw%VPN>+BzKj8;s05fvHD5@3=Qio!6iY1_a{XGhV;kP!VG`r
zOomqephfNt@yehcGbp$iV4iAFw{T@-sDq3cfn+=&)ei&1zLT0<3?E>NG;ui`i*N34
zxOU5ykwFhU(hD+@0m-9S)FXVqFFCEuzv31s=olCproi0J(16&O3U?kUf=4!1Gkkb|
zEo!&=hvu0#ZJ}|bhdokkpmF%XY2A;CsD2B!2mXE-!N!0RD~JSA_y*Jx1C?fb&z^b5
z$uOsd98ZAU3ktZJRWoneK2)udeg0|l`sB4=x9$IZbzjxq)itu^JLSrMS}`>IodYj9
zhzR6{^N^?kna$8}mUz8bW6f#Ff$d;Vf{kN{>40ZOj}DQFuFKGr$M7RmiFKZtF=!wi
ztg`Oa4cms_0$O{nK_VI?*f1T^c+LO1YQ^7~GomB@i@yh@f9p!{Y#B(&1n~GXh{eDO
zX$dhfFbr<N&gAb55AGv{k^WPxxf(6~%+Fc7wfaz)@#Ou_)b~HPz6aXV!NBliBG#k?
zYKR?Z|MA2<mZ9N&GiVJ9AMweRP<e)M7^cd)th6$J28IW0h*AuiOb$$+vxtG=z-nko
z^1~lA#u)b!TEsPc7F1_o_`s*c%Fw|7kPXsh-aQE885DaA3=DC}YqwT|M<;8*!&n7{
zpzTi#4C^3+eR`1H9|s_V#(K~><f~A>GcYuOGV=$yy4COAr=@*oVQ85C={>ltUv~ml
zc;l!OprOgY053mldcdXEgT<X93==OaMKdtS+y|Wt0L~Qf0<oe0fe0%@!(V8;+?nS9
z+8Eb&7c%DbAQsdDehykH!0^K$?}~H!+OKczU;htfU|@K60@l}s8^*xEKvt1UVTnyh
zyUcEO1`$w!KIdBOz1iSU0R=+C{DMhL4BIzc+vQsTDdh{ol~@__TtQn0KzRc+=L=E@
zDZd|-%~=NF6@Zq*K$ytYExz;*F#@88K?qdyx6Zt2+bA9ZuD?Oz2ZSL}aNsHD?f3t^
zrPdiT9I)*WVMti~i0zWGdEvW?=GT4k;N=VqF-PThgJ!cp`WWUr5?!ieCK3{AYLtWr
zO(5$M)|S4yK6|FQE@(jQdf_B+(x-h<3(9Q|Y{6Ls90m>hiMJZ0mw};ScVzb4c^{T0
z-9NMEuW6apZ_~QvyW>I2upjKDq^c`0G~Qgz#Bg9cYMusF@}fU_LmAE;`mVz8;1tXX
zanNSJb?2a&yP)V13&R6Fn4~&r(bPN0q!q}U#8ldQLFt@fe*(C;1!-znZt2PRfazM)
zBFJ1IgP#8qh5|(=P=(3Bz_89|2}6M)ocHR6Ekna=>tu_-+*vc9l$KdO-l}`|?=Nt)
zI`}SOC~(Zym7mANz_7jaTg0{V$qWn(_aU>TAiJ<PSCLX(-(BX4duME}MePQyL;S$_
z=MQK_kIiAI|G}xTKo}f?AoCa)YCM+|D8pRGaL#8*fw8f27(|ZY!4!~r{0o_44kH=|
zCoI72T96VF$|6t^0n%cVop$e^RQB5Z|2LEF->u|lWO#QF*>NB>AdD0h(AM}4zVpn>
zp)IBcb5fHd1H+GtXZ~EP-+%2?95(|)!*k+&0jV;w*WMNOOGU(b|8oM32h=)x$4+>$
z_~2s&BJF~jX?6|J)>(tGMHxQ>gOu@SP_f0xP!O5^fBO^zQP5&-0ZoPj>_0yr`+75f
z12Y4|pLLu6&k26ByLwH@x9mTD<@>iW97qT4X=eX*b++{U8fMU383RMbUVD&<pb%wX
zu!GFJfjER>4&-MBh68s&-K9M<vw1*Unr!LQl0hxWNh|Xi7#PA0jQ9UdzZUiKHE3Vf
zO-LsU-OJFykprE!pMNMYG=OHRKbV|9wO9W-XqgxTLxn1INQ!|0-ZvxHU6?-DHe=>p
zVTOho$Srh`3mF>b1dA{{Foq5?HcW9~WU#xwu^KGL@ImqjCqn~NkKY;g-wX%lf|{EU
zS^71-K}qyMHMkT6TYVrODK8dGV!CtXjLQ1YXYxOXOG7IChGI}N0IZg}J%j^pkb<nh
zsSZ?PJy-{+;MKvqgCCr8;bNG*lMz(@F)$oh4tDnXfW)<1D>)e$Hgq>gGB7mwD+DoE
z2%4)hGB7--{^L_y4{j6;M5qpy?o?-`ja>Hk4&#W^kY(HqbMBvcGmnAc{xgz_J4kGk
z*LcIsFto^oATwM4&j#g0uw(Z<`OL$x4zgkdB%tELWgj39u9q3opBD2lymLTq2L4~*
z1eta@ckH=1!<|--hw(q$AS0A>TF>h;>=2%KsQv>lXw@VG!;Q1gMH%j#wUO)JT7Bf^
z+NZh@W33*sFue0x@<I9tWH{=8b*C`H4(o}BCbxjMUoadf=MZA};erT|kD!Jv$aM@1
z2hs;ik{K%f|50~>QV#tpiqZ553h#kQbqD_6+L{ciej6PBUE6#kR0hNbEt;PI8wYG?
zg%@W!@S;5dbm|Vs)eH>W@K%0=2c&pnU^w6eA9@vo_e3|08aW!43=E@*h+#DMj20W9
z1D{6A%h8I0fnl_UWEgE4FpM@0Mw<qpl{LenVXait`1tUC!OvcxE`q14pUXO@geCwk
Cls-NH

literal 0
HcmV?d00001

diff --git a/serialstep/serialstep-DRV8428P/board/hello.DRV8428P-D11C-NEMA17 b/serialstep/serialstep-DRV8428P/board/hello.DRV8428P-D11C-NEMA17
new file mode 100644
index 0000000..57c445d
--- /dev/null
+++ b/serialstep/serialstep-DRV8428P/board/hello.DRV8428P-D11C-NEMA17
@@ -0,0 +1,8371 @@
+#!/usr/bin/env python3
+#
+# hello.DRV8428P-D11C-NEMA17
+#    DRV8428P NEMA17 stepper hello-world with D11C interface
+#
+# usage:
+#    hello.DRV8428P-D11C-NEMA17 | frep.py [dpi [filename]]
+#
+# Neil Gershenfeld 8/13/21
+# Quentin Bolsee 1/17/22
+#
+# This work may be reproduced, modified, distributed,
+# performed, and displayed for any purpose, but must
+# acknowledge this project. Copyright is retained and
+# must be preserved. The work is provided as is; no
+# warranty is provided, and users accept all liability.
+#
+
+############################################################
+# uncomment for desired output
+############################################################
+
+#output = "top, labels, and exterior"
+output = "top, labels, holes, 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 = "solder mask"
+
+############################################################
+# import
+############################################################
+
+import math,json,sys
+
+############################################################
+# define shapes and transformations
+############################################################
+
+# color(color,part)
+# circle(x,y,r)
+# cylinder(x,y,z0,z1,r)
+# cone(x,y,z0,z1,r)
+# sphere(x,y,z,r)
+# torus(x,y,z,r0,r1)
+# rectangle(x0,x1,y0,y1)
+# cube(x0,x1,y0,y1,z0,z1)
+# line(x0,y0,x1,y1,z,width)
+# right_triangle(x,y,h)
+# 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,x0)
+# reflect_y(part,y0)
+# reflect_z(part,z0)
+# 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)
+
+true = "1"
+false = "0"
+
+def color(color,part):
+   part = '('+str(color)+'*(('+part+')!=0))'
+   return part
+
+Red = (225 << 0)
+Green = (225 << 8)
+Blue = (225 << 16)
+Gray = (128 << 16) + (128 << 8) + (128 << 0)
+White = (255 << 16) + (255 << 8) + (255 << 0)
+Teal = (255 << 16) + (255 << 8)
+Pink = (255 << 16) + (255 << 0)
+Yellow = (255 << 8) + (255 << 0)
+Brown = (45 << 16) + (82 << 8) + (145 << 0)
+Navy = (128 << 16) + (0 << 8) + (0 << 0)
+Tan = (60 << 16) + (90 << 8) + (125 << 0)
+
+def circle(x0,y0,r):
+   part = "(((X-(x0))*(X-(x0)) + (Y-(y0))*(Y-(y0))) <= (r*r))"
+   part = part.replace('x0',str(x0))
+   part = part.replace('y0',str(y0))
+   part = part.replace('r',str(r))
+   return part
+
+def cylinder(x0,y0,z0,z1,r):
+   part = "(((X-(x0))*(X-(x0)) + (Y-(y0))*(Y-(y0)) <= (r*r)) & (Z >= (z0)) & (Z <= (z1)))"
+   part = part.replace('x0',str(x0))
+   part = part.replace('y0',str(y0))
+   part = part.replace('z0',str(z0))
+   part = part.replace('z1',str(z1))
+   part = part.replace('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))*(X-(x0)) + (Y-(y0))*(Y-(y0)) + (Z-(z0))*(Z-(z0))) <= (r*r))"
+   part = part.replace('x0',str(x0))
+   part = part.replace('y0',str(y0))
+   part = part.replace('z0',str(z0))
+   part = part.replace('r',str(r))
+   return part
+
+def torus(x0,y0,z0,r0,r1):
+   part = "(((r0 - sqrt((X-(x0))*(X-(x0)) + (Y-(y0))*(Y-(y0))))*(r0 - sqrt((X-(x0))*(X-(x0)) + (Y-(y0))*(Y-(y0))) + (Z-(z0))*(Z-(z0))) <= (r1*r1))"
+   part = part.replace('x0',str(x0))
+   part = part.replace('y0',str(y0))
+   part = part.replace('z0',str(z0))
+   part = part.replace('r0',str(r0))
+   part = part.replace('r1',str(r1))
+   return part
+
+def rectangle(x0,x1,y0,y1):
+   part = "((X >= (x0)) & (X <= (x1)) & (Y >= (y0)) & (Y <= (y1)))"
+   part = part.replace('x0',str(x0))
+   part = part.replace('x1',str(x1))
+   part = part.replace('y0',str(y0))
+   part = part.replace('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 = part.replace('x0',str(x0))
+   part = part.replace('x1',str(x1))
+   part = part.replace('y0',str(y0))
+   part = part.replace('y1',str(y1))
+   part = part.replace('z0',str(z0))
+   part = part.replace('z1',str(z1))
+   return part
+
+def line(x0,y0,x1,y1,z,width):
+   dx = x1-x0
+   dy = y1-y0
+   l = math.sqrt(dx*dx+dy*dy)
+   nx = dx/l
+   ny = dy/l
+   rx = -ny
+   ry = nx
+   part = "((((X-(x0))*(nx)+(Y-(y0))*(ny)) >= 0) & (((X-(x0))*(nx)+(Y-(y0))*(ny)) <= l) & (((X-(x0))*(rx)+(Y-(y0))*(ry)) >= (-width/2)) & (((X-(x0))*(rx)+(Y-(y0))*(ry)) <= (width/2)) & (Z == z))"
+   part = part.replace('x0',str(x0))
+   part = part.replace('x1',str(x1))
+   part = part.replace('y0',str(y0))
+   part = part.replace('y1',str(y1))
+   part = part.replace('nx',str(nx))
+   part = part.replace('ny',str(ny))
+   part = part.replace('rx',str(rx))
+   part = part.replace('ry',str(ry))
+   part = part.replace('l',str(l))
+   part = part.replace('z',str(z))
+   part = part.replace('width',str(width))
+   return part
+
+def right_triangle(x0,y0,l):
+   part = "((X > x0) & (X < x0 + l - (Y-y0)) & (Y > y0))"
+   part = part.replace('x0',str(x0))
+   part = part.replace('y0',str(y0))
+   part = part.replace('l',str(l))
+   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 = part.replace('x0',str(x0))
+   part = part.replace('y0',str(y0))
+   part = part.replace('x1',str(x1))
+   part = part.replace('y1',str(y1))
+   part = part.replace('x2',str(x2))
+   part = part.replace('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 = part.replace('part1',part1)
+   part = part.replace('part2',part2)
+   return part
+
+def subtract(part1,part2):
+   part = "(part1) & ~(part2)"
+   part = part.replace('part1',part1)
+   part = part.replace('part2',part2)
+   return part
+
+def intersect(part1,part2):
+   part = "(part1) & (part2)"
+   part = part.replace('part1',part1)
+   part = part.replace('part2',part2)
+   return part
+
+def move(part,dx,dy):
+   part = part.replace('X','(X-('+str(dx)+'))')
+   part = part.replace('Y','(Y-('+str(dy)+'))')
+   return part
+
+def translate(part,dx,dy,dz):
+   part = part.replace('X','(X-('+str(dx)+'))')
+   part = part.replace('Y','(Y-('+str(dy)+'))')
+   part = part.replace('Z','(Z-('+str(dz)+'))')
+   return part
+
+def rotate(part,angle):
+   angle = angle*math.pi/180
+   part = part.replace('X','(math.cos(angle)*X+math.sin(angle)*y)')
+   part = part.replace('Y','(-math.sin(angle)*X+math.cos(angle)*y)')
+   part = part.replace('y','Y')
+   part = part.replace('angle',str(angle))
+   return part
+
+def rotate_x(part,angle):
+   angle = angle*math.pi/180
+   part = part.replace('Y','(math.cos(angle)*Y+math.sin(angle)*z)')
+   part = part.replace('Z','(-math.sin(angle)*Y+math.cos(angle)*z)')
+   part = part.replace('z','Z')
+   part = part.replace('angle',str(angle))
+   return part
+
+def rotate_y(part,angle):
+   angle = angle*math.pi/180
+   part = part.replace('X','(math.cos(angle)*X+math.sin(angle)*z)')
+   part = part.replace('Z','(-math.sin(angle)*X+math.cos(angle)*z)')
+   part = part.replace('z','Z')
+   part = part.replace('angle',str(angle))
+   return part
+
+def rotate_z(part,angle):
+   angle = angle*math.pi/180
+   part = part.replace('X','(math.cos(angle)*X+math.sin(angle)*y)')
+   part = part.replace('Y','(-math.sin(angle)*X+math.cos(angle)*y)')
+   part = part.replace('y','Y')
+   part = part.replace('angle',str(angle))
+   return part
+
+def rotate_90(part):
+   part = reflect_y(part,0)
+   part = reflect_xy(part)
+   return part
+
+def rotate_180(part):
+   part = rotate_90(part)
+   part = rotate_90(part)
+   return part
+
+def rotate_270(part):
+   part = rotate_90(part)
+   part = rotate_90(part)
+   part = rotate_90(part)
+   return part
+
+def reflect_x(part,x0):
+   part = part.replace('X','(x0-X)')
+   part = part.replace('x0',str(x0))
+   return part
+
+def reflect_y(part,y0):
+   part = part.replace('Y','(y0-Y)')
+   part = part.replace('y0',str(y0))
+   return part
+
+def reflect_z(part,z0):
+   part = part.replace('Z','(z0-Z)')
+   part = part.replace('z0',str(z0))
+   return part
+
+def reflect_xy(part):
+   part = part.replace('X','temp')
+   part = part.replace('Y','X')
+   part = part.replace('temp','Y')
+   return part
+
+def reflect_xz(part):
+   part = part.replace('X','temp')
+   part = part.replace('Z','X')
+   part = part.replace('temp','Z')
+   return part
+
+def reflect_yz(part):
+   part = part.replace('Y','temp')
+   part = part.replace('Z','Y')
+   part = part.replace('temp','Z')
+   return part
+
+def scale_x(part,x0,sx):
+   part = part.replace('X','((x0) + (X-(x0))/(sx))')
+   part = part.replace('x0',str(x0))
+   part = part.replace('sx',str(sx))
+   return part
+
+def scale_y(part,y0,sy):
+   part = part.replace('Y','((y0) + (Y-(y0))/(sy))')
+   part = part.replace('y0',str(y0))
+   part = part.replace('sy',str(sy))
+   return part
+
+def scale_z(part,z0,sz):
+   part = part.replace('Z','((z0) + (Z-(z0))/(sz))')
+   part = part.replace('z0',str(z0))
+   part = part.replace('sz',str(sz))
+   return part
+
+def scale_xy(part,x0,y0,sxy):
+   part = part.replace('X','((x0) + (X-(x0))/(sxy))')
+   part = part.replace('Y','((y0) + (Y-(y0))/(sxy))')
+   part = part.replace('x0',str(x0))
+   part = part.replace('y0',str(y0))
+   part = part.replace('sxy',str(sxy))
+   return part
+
+def scale_xyz(part,x0,y0,z0,sxyz):
+   part = part.replace('X','((x0) + (X-(x0))/(sxyz))')
+   part = part.replace('Y','((y0) + (Y-(y0))/(sxyz))')
+   part = part.replace('Z','((z0) + (Z-(z0))/(sxyz))')
+   part = part.replace('x0',str(x0))
+   part = part.replace('y0',str(y0))
+   part = part.replace('z0',str(z0))
+   part = part.replace('sxyz',str(sxyz))
+   return part
+
+def coscale_x_y(part,x0,y0,y1,angle0,angle1,amplitude,offset):
+   phase0 = math.pi*angle0/180.
+   phase1 = math.pi*angle1/180.
+   part = part.replace('X','((x0) + (X-(x0))/((offset) + (amplitude)*math.cos((phase0) + ((phase1)-(phase0))*(Y-(y0))/((y1)-(y0)))))')
+   part = part.replace('x0',str(x0))
+   part = part.replace('y0',str(y0))
+   part = part.replace('y1',str(y1))
+   part = part.replace('phase0',str(phase0))
+   part = part.replace('phase1',str(phase1))
+   part = part.replace('amplitude',str(amplitude))
+   part = part.replace('offset',str(offset))
+   return part
+
+def coscale_x_z(part,x0,z0,z1,angle0,angle1,amplitude,offset):
+   phase0 = math.pi*angle0/180.
+   phase1 = math.pi*angle1/180.
+   part = part.replace('X','((x0) + (X-(x0))/((offset) + (amplitude)*math.cos((phase0) + ((phase1)-(phase0))*(Z-(z0))/((z1)-(z0)))))')
+   part = part.replace('x0',str(x0))
+   part = part.replace('z0',str(z0))
+   part = part.replace('z1',str(z1))
+   part = part.replace('phase0',str(phase0))
+   part = part.replace('phase1',str(phase1))
+   part = part.replace('amplitude',str(amplitude))
+   part = part.replace('offset',str(offset))
+   return part
+
+def coscale_xy_z(part,x0,y0,z0,z1,angle0,angle1,amplitude,offset):
+   phase0 = math.pi*angle0/180.
+   phase1 = math.pi*angle1/180.
+   part = part.replace('X','((x0) + (X-(x0))/((offset) + (amplitude)*math.cos((phase0) + ((phase1)-(phase0))*(Z-(z0))/((z1)-(z0)))))')
+   part = part.replace('Y','((y0) + (Y-(y0))/((offset) + (amplitude)*math.cos((phase0) + ((phase1)-(phase0))*(Z-(z0))/((z1)-(z0)))))')
+   part = part.replace('x0',str(x0))
+   part = part.replace('y0',str(y0))
+   part = part.replace('z0',str(z0))
+   part = part.replace('z1',str(z1))
+   part = part.replace('phase0',str(phase0))
+   part = part.replace('phase1',str(phase1))
+   part = part.replace('amplitude',str(amplitude))
+   part = part.replace('offset',str(offset))
+   return part
+
+def taper_x_y(part,x0,y0,y1,s0,s1):
+   part = part.replace('X','((x0) + (X-(x0))*((y1)-(y0))/((s1)*(Y-(y0)) + (s0)*((y1)-Y)))')
+   part = part.replace('x0',str(x0))
+   part = part.replace('y0',str(y0))
+   part = part.replace('y1',str(y1))
+   part = part.replace('s0',str(s0))
+   part = part.replace('s1',str(s1))
+   return part
+
+def taper_x_z(part,x0,z0,z1,s0,s1):
+   part = part.replace('X','((x0) + (X-(x0))*((z1)-(z0))/((s1)*(Z-(z0)) + (s0)*((z1)-Z)))')
+   part = part.replace('x0',str(x0))
+   part = part.replace('z0',str(z0))
+   part = part.replace('z1',str(z1))
+   part = part.replace('s0',str(s0))
+   part = part.replace('s1',str(s1))
+   return part
+
+def taper_xy_z(part,x0,y0,z0,z1,s0,s1):
+   part = part.replace('X','((x0) + (X-(x0))*((z1)-(z0))/((s1)*(Z-(z0)) + (s0)*((z1)-Z)))')
+   part = part.replace('Y','((y0) + (Y-(y0))*((z1)-(z0))/((s1)*(Z-(z0)) + (s0)*((z1)-Z)))')
+   part = part.replace('x0',str(x0))
+   part = part.replace('y0',str(y0))
+   part = part.replace('z0',str(z0))
+   part = part.replace('z1',str(z1))
+   part = part.replace('s0',str(s0))
+   part = part.replace('s1',str(s1))
+   return part
+
+def shear_x_y(part,y0,y1,dx0,dx1):
+   part = part.replace('X','(X - (dx0) - ((dx1)-(dx0))*(Y-(y0))/((y1)-(y0)))')
+   part = part.replace('y0',str(y0))
+   part = part.replace('y1',str(y1))
+   part = part.replace('dx0',str(dx0))
+   part = part.replace('dx1',str(dx1))
+   return part
+
+def shear_x_z(part,z0,z1,dx0,dx1):
+   part = part.replace('X','(X - (dx0) - ((dx1)-(dx0))*(Z-(z0))/((z1)-(z0)))')
+   part = part.replace('z0',str(z0))
+   part = part.replace('z1',str(z1))
+   part = part.replace('dx0',str(dx0))
+   part = part.replace('dx1',str(dx1))
+   return part
+
+def coshear_x_z(part,z0,z1,angle0,angle1,amplitude,offset):
+   phase0 = math.pi*angle0/180.
+   phase1 = math.pi*angle1/180.
+   part = part.replace('X','(X - (offset) - (amplitude)*math.cos((phase0) + ((phase1)-(phase0))*(Z-(z0))/((z1)-(z0))))')
+   part = part.replace('z0',str(z0))
+   part = part.replace('z1',str(z1))
+   part = part.replace('phase0',str(phase0))
+   part = part.replace('phase1',str(phase1))
+   part = part.replace('amplitude',str(amplitude))
+   part = part.replace('offset',str(offset))
+   return part
+
+############################################################
+# text classes and definitions
+############################################################
+
+class text:
+   #
+   # text class
+   #
+   def __init__(self,text,x,y,z=0,line='',height='',width='',space='',align='CC',color=White,angle=0):
+      #
+      # parameters
+      #
+      if (line == ''):
+         line = 1
+      if (height == ''):
+         height = 6*line
+      if (width == ''):
+         width = 4*line
+      if (space == ''):
+         space = line/2.0
+      self.width = 0
+      self.height = 0
+      self.text = text
+      #
+      # construct shape dictionary
+      #
+      shapes = {}
+      shape = triangle(0,0,width/2.0,height,width,0)
+      cutout = triangle(0,-2.5*line,width/2.0,height-2.5*line,width,-2.5*line)
+      cutout = subtract(cutout,rectangle(0,width,height/4-line/2,height/4+line/2))
+      shape = subtract(shape,cutout)
+      shapes['A'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = subtract(shape,circle(width/2,width/2,width/4))
+      shape = add(shape,rectangle(width-line,width,0,height/3))
+      shapes['a'] = shape
+      shape = rectangle(0,width-height/4,0,height)
+      shape = add(shape,circle(width-height/4,height/4,height/4))
+      shape = add(shape,circle(width-height/4,3*height/4,height/4))
+      w = height/2-1.5*line
+      shape = subtract(shape,rectangle(line,line+w/1.5,height/2+line/2,height-line))
+      shape = subtract(shape,circle(line+w/1.5,height/2+line/2+w/2,w/2))
+      shape = subtract(shape,rectangle(line,line+w/1.5,line,height/2-line/2))
+      shape = subtract(shape,circle(line+w/1.5,height/2-line/2-w/2,w/2))
+      shapes['B'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = subtract(shape,circle(width/2,width/2,width/4))
+      shape = add(shape,rectangle(0,line,0,height))
+      shapes['b'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = add(shape,circle(width/2,height-width/2,width/2))
+      shape = add(shape,rectangle(0,width,line+w/2,height-line-w/2))
+      w = width-2*line
+      shape = subtract(shape,circle(width/2,line+w/2,w/2))
+      shape = subtract(shape,circle(width/2,height-line-w/2,w/2))
+      shape = subtract(shape,rectangle(line,width,line+w/2,height-line-w/2))
+      shapes['C'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = subtract(shape,circle(width/2,width/2,width/4))
+      shape = subtract(shape,rectangle(width/2,width,width/2-line/1.5,width/2+line/1.5))
+      shapes['c'] = shape
+      shape = circle(line,width-line,width-line)
+      shape = subtract(shape,circle(line,width-line,width-2*line))
+      shape = subtract(shape,rectangle(-width,line,0,height))
+      shape = scale_y(shape,0,height/(2*(width-line)))
+      shape = add(shape,rectangle(0,line,0,height))
+      shapes['D'] = shape
+      shape = rectangle(width-line,width,0,height)
+      shape = add(shape,circle(width/2,width/2,width/2))
+      shape = subtract(shape,circle(width/2,width/2,width/2-line))
+      shapes['d'] = shape
+      shape = rectangle(0,line,0,height)
+      shape = add(shape,rectangle(0,width,height-line,height))
+      shape = add(shape,rectangle(0,2*width/3,height/2-line/2,height/2+line/2))
+      shape = add(shape,rectangle(0,width,0,line))
+      shapes['E'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = subtract(shape,circle(width/2,width/2,width/2-line))
+      shape = subtract(shape,triangle(width,0,width/2,width/2-line/2,width,width/2-line/2))
+      shape = add(shape,rectangle(0,width,width/2-line/2,width/2+line/2))
+      shapes['e'] = shape
+      shape = rectangle(0,line,0,height)
+      shape = add(shape,rectangle(0,width,height-line,height))
+      shape = add(shape,rectangle(0,2*width/3,height/2-line/2,height/2+line/2))
+      shapes['F'] = shape
+      shape = circle(width-line/2,height-width/2,width/2)
+      shape = subtract(shape,circle(width-line/2,height-width/2,width/2-line))
+      shape = subtract(shape,rectangle(0,width-line/2,0,height-width/2))
+      shape = subtract(shape,rectangle(width-line/2,2*width,0,height))
+      shape = add(shape,rectangle(width/2-line/2,width/2+line/2,0,height-width/2))
+      shape = add(shape,rectangle(width/5,4*width/5,height/2-line/2,height/2+line/2))
+      shapes['f'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = add(shape,circle(width/2,height-width/2,width/2))
+      shape = add(shape,rectangle(0,width,line+w/2,height-line-w/2))
+      w = width-2*line
+      shape = subtract(shape,circle(width/2,line+w/2,w/2))
+      shape = subtract(shape,circle(width/2,height-line-w/2,w/2))
+      shape = subtract(shape,rectangle(line,width,line+w/2,height-line-w/2))
+      shape = add(shape,rectangle(width/2,width,line+w/2,2*line+w/2))
+      shapes['G'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = subtract(shape,circle(width/2,width/2,width/2-line))
+      w = height/3-width/2
+      shape = add(shape,rectangle(width-line,width,w,width))
+      shape = add(shape,subtract(subtract(circle(width/2,w,width/2),circle(width/2,w,width/2-line)),rectangle(0,width,w,height)))
+      shapes['g'] = shape
+      shape = rectangle(0,line,0,height)
+      shape = add(shape,rectangle(width-line,width,0,height))
+      shape = add(shape,rectangle(0,width,height/2-line/2,height/2+line/2))
+      shapes['H'] = shape
+      w = width/2
+      shape = circle(width/2,w,width/2)
+      shape = subtract(shape,circle(width/2,w,width/2-line))
+      shape = subtract(shape,rectangle(0,width,0,w))
+      shape = add(shape,rectangle(0,line,0,height))
+      shape = add(shape,rectangle(width-line,width,0,w))
+      shapes['h'] = shape
+      shape = rectangle(width/2-line/2,width/2+line/2,0,height)
+      shape = add(shape,rectangle(width/5,4*width/5,0,line))
+      shape = add(shape,rectangle(width/5,4*width/5,height-line,height))
+      shapes['I'] = shape
+      shape = rectangle(width/2-line/2,width/2+line/2,0,height/2)
+      shape = add(shape,circle(width/2,3*height/4,.6*line))
+      shapes['i'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = subtract(shape,circle(width/2,width/2,width/2-line))
+      shape = subtract(shape,rectangle(0,width,width/2,height))
+      shape = add(shape,rectangle(width-line,width,width/2,height))
+      shapes['J'] = shape
+      w = height/3-width/2
+      shape = rectangle(width/2-line/2,width/2+line/2,w,height/2)
+      shape = add(shape,subtract(subtract(subtract(circle(width/4-line/2,w,width/2),circle(width/4-line/2,w,width/2-line)),rectangle(0,width,w,height)),rectangle(-width,width/4-line/2,-height/3,height)))
+      shape = add(shape,circle(width/2,3*height/4,.6*line))
+      shapes['j'] = shape
+      shape = rectangle(0,width,0,height)
+      shape = subtract(shape,triangle(line,height,width-1.1*line,height,line,height/2+.5*line))
+      shape = subtract(shape,triangle(width,0,line+0.8*line,height/2,width,height))
+      shape = subtract(shape,triangle(line,0,line,height/2-.5*line,width-1.1*line,0))
+      shapes['K'] = shape
+      shape = rectangle(0,width,0,height)
+      shape = subtract(shape,rectangle(line,width,2*height/3,height))
+      shape = subtract(shape,triangle(line,2*height/3,width-1.3*line,2*height/3,line,height/3+.5*line))
+      shape = subtract(shape,triangle(width,0,line+0.8*line,height/3,width,2*height/3))
+      shape = subtract(shape,triangle(line,0,line,height/3-0.5*line,width-1.3*line,0))
+      shapes['k'] = shape
+      shape = rectangle(0,line,0,height)
+      shape = add(shape,rectangle(0,width,0,line))
+      shapes['L'] = shape
+      shape = rectangle(width/2-line/2,width/2+line/2,0,height)
+      shapes['l'] = shape
+      shape = rectangle(0,width,0,height)
+      shape = subtract(shape,triangle(line,0,line,height-3*line,width/2-line/3,0))
+      shape = subtract(shape,triangle(line,height,width-line,height,width/2,1.5*line))
+      shape = subtract(shape,triangle(width/2+line/3,0,width-line,height-3*line,width-line,0))
+      shapes['M'] = shape
+      w = width/2
+      l = 1.3*line
+      shape = circle(width/2,w,width/2)
+      shape = subtract(shape,circle(width/2,w,width/2-l))
+      shape = subtract(shape,rectangle(0,width,0,w))
+      shape = add(shape,rectangle(width-l,width,0,w))
+      shape = add(shape,move(shape,width-l,0))
+      shape = add(shape,rectangle(0,l,0,width))
+      shape = scale_x(shape,0,width/(2*width-l))
+      shapes['m'] = shape
+      shape = rectangle(0,width,0,height)
+      shape = subtract(shape,triangle(line,height+1.5*line,width-line,height+1.5*line,width-line,1.5*line))
+      shape = subtract(shape,triangle(line,-1.5*line,line,height-1.5*line,width-line,-1.5*line))
+      shapes['N'] = shape
+      w = width/2
+      shape = circle(width/2,w,width/2)
+      shape = subtract(shape,circle(width/2,w,width/2-line))
+      shape = subtract(shape,rectangle(0,width,0,w))
+      shape = add(shape,rectangle(0,line,0,width))
+      shape = add(shape,rectangle(width-line,width,0,w))
+      shapes['n'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = add(shape,circle(width/2,height-width/2,width/2))
+      shape = add(shape,rectangle(0,width,line+w/2,height-line-w/2))
+      w = width-2*line
+      shape = subtract(shape,circle(width/2,line+w/2,w/2))
+      shape = subtract(shape,circle(width/2,height-line-w/2,w/2))
+      shape = subtract(shape,rectangle(line,width-line,line+w/2,height-line-w/2))
+      shapes['O'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = subtract(shape,circle(width/2,width/2,width/2-line))
+      shapes['o'] = shape
+      shape = rectangle(0,line,0,height)
+      w = 2*height/3
+      shape = add(shape,circle(width-w/2,height-w/2,w/2))
+      shape = add(shape,rectangle(0,width-w/2,height-w,height))
+      shape = subtract(shape,circle(width-w/2,height-w/2,w/2-line))
+      shape = subtract(shape,rectangle(line,width-w/2,height-w+line,height-line))
+      shapes['P'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = subtract(shape,circle(width/2,width/2,width/4))
+      shape = add(shape,rectangle(0,line,-height/3,width))
+      shapes['p'] = shape
+      shape = subtract(circle(width/2,width/2,width/2),circle(width/2,width/2,width/2-.9*line))
+      shape = scale_y(shape,0,height/width)
+      shape = add(shape,move(rotate(rectangle(-line/2,line/2,-width/4,width/4),30),3*width/4,width/4))
+      shapes['Q'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = subtract(shape,circle(width/2,width/2,width/2-line))
+      shape = add(shape,rectangle(width-line,width,-height/3,width))
+      shapes['q'] = shape
+      shape = rectangle(0,line,0,height)
+      w = 2*height/3
+      shape = add(shape,circle(width-w/2,height-w/2,w/2))
+      shape = add(shape,rectangle(0,width-w/2,height-w,height))
+      shape = subtract(shape,circle(width-w/2,height-w/2,w/2-line))
+      shape = subtract(shape,rectangle(line,width-w/2,height-w+line,height-line))
+      leg = triangle(line,0,line,height,width,0)
+      leg = subtract(leg,triangle(line,-2.0*line,line,height-2.0*line,width,-2.0*line))
+      leg = subtract(leg,rectangle(0,width,height/3,height))
+      shape = add(shape,leg)
+      shapes['R'] = shape
+      shape = circle(width,0,width)
+      shape = subtract(shape,circle(width,0,width-line))
+      shape = subtract(shape,rectangle(.8*width,2*width,-height,height))
+      shape = subtract(shape,rectangle(0,2*width,-height,0))
+      shape = add(shape,rectangle(0,line,0,width))
+      shapes['r'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = subtract(shape,circle(width/2,width/2,width/2-line))
+      shape = subtract(shape,rectangle(0,width/2,width/2,width))
+      shape = add(shape,move(reflect_y(reflect_x(shape,width),width),0,width-line))
+      shape = scale_y(shape,0,height/(2*width-line))
+      shapes['S'] = shape
+      w = width/3
+      shape = circle(w,w,w)
+      shape = subtract(shape,circle(w,w,w-.9*line))
+      shape = subtract(shape,rectangle(0,w,w,2*w))
+      shape = add(shape,move(reflect_y(reflect_x(shape,2*w),2*w),0,2*w-.9*line))
+      shape = scale_y(shape,0,(2*height/3)/(4*w-.9*line))
+      shape = move(shape,(width/2)-w,0)
+      shapes['s'] = shape
+      shape = rectangle(width/2-line/2,width/2+line/2,0,height)
+      shape = add(shape,rectangle(0,width,height-line,height))
+      shapes['T'] = shape
+      shape = circle(0,3*width/8,3*width/8)
+      shape = subtract(shape,circle(0,3*width/8,3*width/8-line))
+      shape = subtract(shape,rectangle(-width,width,3*width/8,height))
+      shape = subtract(shape,rectangle(0,width,-height,height))
+      shape = move(shape,width/2-line/2+3*width/8,0)
+      shape = add(shape,rectangle(width/2-line/2,width/2+line/2,width/4,3*height/4))
+      shape = add(shape,rectangle(width/5,4*width/5,height/2-line/2,height/2+line/2))
+      shapes['t'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = subtract(shape,circle(width/2,width/2,width/2-line))
+      shape = subtract(shape,rectangle(0,width,width/2,height))
+      shape = add(shape,rectangle(0,line,width/2,height))
+      shape = add(shape,rectangle(width-line,width,width/2,height))
+      shapes['U'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = subtract(shape,circle(width/2,width/2,width/2-line))
+      shape = subtract(shape,rectangle(0,width,width/2,height))
+      shape = add(shape,rectangle(0,line,width/2,2*height/3))
+      shape = add(shape,rectangle(width-line,width,0,2*height/3))
+      shapes['u'] = shape
+      shape = triangle(0,height,width,height,width/2,0)
+      shape = subtract(shape,triangle(0,height+3*line,width,height+3*line,width/2,3*line))
+      shapes['V'] = shape
+      w = 2*height/3.0
+      shape = triangle(0,w,width,w,width/2,0)
+      shape = subtract(shape,triangle(0,w+2*line,width,w+2*line,width/2,2*line))
+      shapes['v'] = shape
+      shape = triangle(0,height,width,height,width/2,0)
+      shape = add(shape,move(shape,.6*width,0))
+      cutout = triangle(0,height+4*line,width,height+4*line,width/2,4*line)
+      cutout = add(cutout,move(cutout,.6*width,0))
+      shape = subtract(shape,cutout)
+      shape = scale_x(shape,0,1/1.6)
+      shapes['W'] = shape
+      shape = scale_y(shapes['W'],0,width/height)
+      shapes['w'] = shape
+      shape = rectangle(0,width,0,height)
+      shape = subtract(shape,triangle(0,0,0,height,width/2-.7*line,height/2))
+      shape = subtract(shape,triangle(width,0,width/2+.7*line,height/2,width,height))
+      shape = subtract(shape,triangle(1.1*line,height,width-1.1*line,height,width/2,height/2+line))
+      shape = subtract(shape,triangle(1.1*line,0,width/2,height/2-line,width-1.1*line,0))
+      shapes['X'] = shape
+      w = 2*height/3.0
+      shape = rectangle(0,width,0,w)
+      shape = subtract(shape,triangle(0,0,0,w,width/2-.75*line,w/2))
+      shape = subtract(shape,triangle(width,0,width/2+.75*line,w/2,width,w))
+      shape = subtract(shape,triangle(1.25*line,0,width/2,w/2-.75*line,width-1.25*line,0))
+      shape = subtract(shape,triangle(1.25*line,w,width-1.25*line,w,width/2,w/2+.75*line))
+      shapes['x'] = shape
+      w = height/2
+      shape = rectangle(0,width,w,height)
+      shape = subtract(shape,triangle(0,w,0,height,width/2-line/2,w))
+      shape = subtract(shape,triangle(width/2+line/2,w,width,height,width,w))
+      shape = subtract(shape,triangle(1.1*line,height,width-1.1*line,height,width/2,w+1.1*line))
+      shape = add(shape,rectangle(width/2-line/2,width/2+line/2,0,w))
+      shapes['Y'] = shape
+      shape = rectangle(0,width,-height/3,width)
+      shape = subtract(shape,triangle(0,-height/3,0,width,width/2-.9*line,0))
+      shape = subtract(shape,triangle(1.1*line,width,width-1.1*line,width,width/2-.2*line,1.6*line))
+      shape = subtract(shape,triangle(1.2*line,-height/3,width,width,width,-height/3))
+      shapes['y'] = shape
+      shape = rectangle(0,width,0,height)
+      shape = subtract(shape,triangle(0,line,0,height-line,width-1.4*line,height-line))
+      shape = subtract(shape,triangle(1.4*line,line,width,height-line,width,line))
+      shapes['Z'] = shape
+      w = 2*height/3
+      shape = rectangle(0,width,0,w)
+      shape = subtract(shape,triangle(0,line,0,w-line,width-1.6*line,w-line))
+      shape = subtract(shape,triangle(width,line,1.6*line,line,width,w-line))
+      shapes['z'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = subtract(shape,circle(width/2,width/2,width/2-.9*line))
+      shape = scale_y(shape,0,height/width)
+      shapes['0'] = shape
+      shape = rectangle(width/2-line/2,width/2+line/2,0,height)
+      w = width/2-line/2
+      cutout = circle(0,height,w)
+      shape = add(shape,rectangle(0,width/2,height-w-line,height))
+      shape = subtract(shape,cutout)
+      shape = move(shape,(width/2+line/2)/4,0)
+      shapes['1'] = shape
+      shape = circle(width/2,height-width/2,width/2)
+      shape = subtract(shape,circle(width/2,height-width/2,width/2-line))
+      shape = subtract(shape,rectangle(0,width/2,0,height-width/2))
+      shape = add(shape,rectangle(0,width,0,height-width/2))
+      shape = subtract(shape,triangle(0,line,0,height-width/2,width-line,height-width/2))
+      shape = subtract(shape,triangle(1.5*line,line,width,height-width/2-.5*line,width,line))
+      shapes['2'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = subtract(shape,circle(width/2,width/2,width/2-line))
+      shape = scale_y(shape,0,(height/2+line/2)/width)
+      shape = add(shape,move(shape,0,height/2-line/2))
+      shape = subtract(shape,rectangle(0,width/2,height/4,3*height/4))
+      shapes['3'] = shape
+      shape = rectangle(width-line,width,0,height)
+      shape = add(shape,triangle(0,height/3,width-line,height,width-line,height/3))
+      shape = subtract(shape,triangle(1.75*line,height/3+line,width-line,height-1.5*line,width-line,height/3+line))
+      shapes['4'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = subtract(shape,circle(width/2,width/2,width/2-line))
+      shape = subtract(shape,rectangle(0,width/2,width/2,width))
+      shape = add(shape,rectangle(0,width/2,width-line,width))
+      shape = add(shape,rectangle(0,line,width-line,height))
+      shape = add(shape,rectangle(0,width,height-line,height))
+      shapes['5'] = shape
+      shape = circle(width/2,height-width/2,width/2)
+      shape = subtract(shape,circle(width/2,height-width/2,width/2-line))
+      shape = subtract(shape,rectangle(0,width,0,height-width/2))
+      shape = subtract(shape,triangle(width,height,width,height/2,width/2,height/2))
+      shape = add(shape,circle(width/2,width/2,width/2))
+      shape = subtract(shape,circle(width/2,width/2,width/2-line))
+      shape = add(shape,rectangle(0,line,width/2,height-width/2))
+      shapes['6'] = shape
+      shape = rectangle(0,width,0,height)
+      shape = subtract(shape,triangle(0,0,0,height-line,width-line,height-line))
+      shape = subtract(shape,triangle(line,0,width,height-line,width,0))
+      shapes['7'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = subtract(shape,circle(width/2,width/2,width/2-line))
+      shape = scale_y(shape,0,(height/2+line/2)/width)
+      shape = add(shape,move(shape,0,height/2-line/2))
+      shapes['8'] = shape
+      shape = circle(width/2,width/2,width/2)
+      shape = subtract(shape,circle(width/2,width/2,width/2-line))
+      shape = subtract(shape,rectangle(0,width,width/2,height))
+      shape = subtract(shape,triangle(0,0,0,height/2,width/2,height/2))
+      shape = add(shape,circle(width/2,height-width/2,width/2))
+      shape = subtract(shape,circle(width/2,height-width/2,width/2-line))
+      shape = add(shape,rectangle(width-line,width,width/2,height-width/2))
+      shapes['9'] = shape
+      w = width/2
+      shape = circle(w,w,w)
+      shape = subtract(shape,circle(w,w,w-line))
+      shape = subtract(shape,rectangle(w,width,0,height))
+      shape = scale_y(shape,0,height/width)
+      shape = move(shape,w/2,0)
+      shapes['('] = shape
+      shape = reflect_x(shape,width)
+      shapes[')'] = shape
+      shapes[' '] = false
+      shape = rectangle(width/2-width/3,width/2+width/3,height/2-line/2,height/2+line/2)
+      shape = add(shape,rectangle(width/2-line/2,width/2+line/2,height/2-width/3,height/2+width/3))
+      shapes['+'] = shape
+      shape = rectangle(width/2-width/3,width/2+width/3,height/2-line/2,height/2+line/2)
+      shapes['-'] = shape
+      shape = circle(width/2,line,.75*line)
+      shapes['.'] = shape
+      shape = rectangle(0,width,0,height)
+      d = .8*line
+      shape = subtract(shape,triangle(d,0,width,height-d,width,0))
+      shape = subtract(shape,triangle(0,d,0,height,width-d,height))
+      shapes['/'] = shape
+      #
+      # to be done
+      #
+      shapes['*'] = shape
+      shapes['~'] = shape
+      shapes['!'] = shape
+      shapes['@'] = shape
+      shapes['#'] = shape
+      shapes['$'] = shape
+      shapes['%'] = shape
+      shapes['^'] = shape
+      shapes['&'] = shape
+      shapes['&'] = shape
+      shapes['_'] = shape
+      shapes['='] = shape
+      shapes['['] = shape
+      shapes['{'] = shape
+      shapes[']'] = shape
+      shapes['}'] = shape
+      shapes[';'] = shape
+      shapes[':'] = shape
+      shapes["'"] = shape
+      shapes['"'] = shape
+      shapes[','] = shape
+      shapes['<'] = shape
+      shapes['>'] = shape
+      shapes['?'] = shape
+      #
+      # add a line to text shape
+      #
+      def addline(lineshape):
+         #
+         # LR align
+         #
+         if (align[0] == 'C'):
+            lineshape = move(lineshape,-self.width/2.0,0)
+         elif (align[0] == 'R'):
+            lineshape = move(lineshape,-self.width,0)
+         #
+         # add
+         #
+         self.shape = add(self.shape,lineshape)
+      #
+      # loop over chars
+      #
+      dx = 0
+      dy = -height
+      self.width = -space
+      self.height = height
+      lineshape = false
+      self.shape = false
+      count = 0
+      for chr in text:
+         if (chr == '\n'):
+            count += 1
+            addline(lineshape)
+            dx = 0
+            dy -= 1.5*self.height/(1+(count-1)*1.5)
+            self.width = -space
+            self.height += 1.5*self.height
+            lineshape = false
+         else:
+            lineshape = add(lineshape,move(shapes[chr],dx,dy))
+            self.width += space + width
+            dx += width + space
+      addline(lineshape)
+      #
+      # UD align
+      #
+      if (align[1] == 'C'):
+         self.shape = move(self.shape,0,self.height/2.0)
+      elif (align[1] == 'B'):
+         self.shape = move(self.shape,0,self.height)
+      #
+      # rotate
+      #
+      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)
+      elif (angle != 0):
+         self.shape = rotate(self.shape,angle)
+      #
+      # translate
+      #
+      self.shape = move(self.shape,x,y)
+      #
+      # color
+      #
+      self.shape = '('+str(color)+'*(('+self.shape+')!=0))'
+
+############################################################
+# PCB classes and definitions
+############################################################
+
+class PCB:
+   def __init__(self,x0,y0,width,height,mask):
+      self.board = false
+      self.labels = false
+      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
+      self.cutout = 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 point:
+   def __init__(self,x,y,z=0):
+      self.x = x
+      self.y = y
+      self.z = z
+
+class part:
+   class text:
+      def __init__(self,x,y,z=0,text='',line=0.006,angle=0):
+         self.x = x
+         self.y = y
+         self.z = z
+         self.text = text
+         self.line = line
+         self.angle = angle
+   def add(self,pcb,x,y,z=0,angle=0,line=0.007):
+      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)
+      elif (angle != 0):
+         self.shape = rotate(self.shape,angle)
+      self.shape = translate(self.shape,x,y,z)
+      if hasattr(self,'holes'):
+         if (angle == 90):
+            self.holes = rotate_90(self.holes)
+         elif (angle == 180):
+            self.holes = rotate_180(self.holes)
+         elif ((angle == 270) | (angle == -90)):
+            self.holes = rotate_270(self.holes)
+         elif (angle != 0):
+            self.holes = rotate(self.holes,angle)
+         self.holes = translate(self.holes,x,y,z)
+      if hasattr(self,'cutout'):
+         if (angle == 90):
+            self.cutout = rotate_90(self.cutout)
+         elif (angle == 180):
+            self.cutout = rotate_180(self.cutout)
+         elif ((angle == 270) | (angle == -90)):
+            self.cutout = rotate_270(self.cutout)
+         elif (angle != 0):
+            self.cutout = rotate(self.cutout,angle)
+         self.cutout = translate(self.cutout,x,y,z)
+      deg_angle = angle
+      angle = math.pi*angle/180
+      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
+         self.pad[i].x = x + xnew
+         self.pad[i].y = y + ynew
+         self.pad[i].z += z
+      pcb.labels = add(pcb.labels,text(self.value,x,y,z,line=line,color=Green).shape)
+      for i in range(len(self.labels)):
+         xnew = math.cos(angle)*self.labels[i].x - math.sin(angle)*self.labels[i].y
+         ynew = math.sin(angle)*self.labels[i].x + math.cos(angle)*self.labels[i].y
+         self.labels[i].x = x + xnew
+         self.labels[i].y = y + ynew
+         self.labels[i].z += z
+         if ((-90 < deg_angle) & (deg_angle <= 90)):
+            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).shape)
+         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)
+      if hasattr(self,'holes'):
+         pcb.holes = add(pcb.holes,self.holes)
+      if hasattr(self,'cutout'):
+         pcb.interior = subtract(pcb.interior,self.cutout)
+         pcb.exterior = add(pcb.exterior,self.cutout)
+      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))
+   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
+      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 wirer(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
+############################################################
+
+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))
+
+class SJ(part):
+   #
+   # solder jumper
+   #
+   def __init__(self,value=''):
+      pad_SJ = cube(-.02,.02,-.03,.03,0,0)
+      self.value = value
+      self.labels = []
+      self.pad = [point(0,0,0)]
+      self.shape = translate(pad_SJ,-.029,0,0)
+      self.pad.append(point(-.029,0,0))
+      self.shape = add(self.shape,translate(pad_SJ,.029,0,0))
+      self.pad.append(point(.029,0,0))
+
+############################################################
+# discretes
+############################################################
+
+
+class ST4EB(part):
+   #
+   # Nidec Copal ST4ETB103 trimpot
+   #
+   def __init__(self,value=''):
+      pad1 = cube(-.032,.032,-.039,.039,0,0)
+      pad2 = cube(-.039,.039,-.039,.039,0,0)
+      self.value = value
+      self.labels = []
+      self.pad = [point(0,0,0)]
+      self.shape = translate(pad1,-.046,-.118,0)
+      self.pad.append(point(-.046,-.118,0))
+      self.shape = add(self.shape,translate(pad1,.046,-.118,0))
+      self.pad.append(point(.046,-.118,0))
+      self.shape = add(self.shape,translate(pad2,0,.118,0))
+      self.pad.append(point(0,.118,0))
+
+class C_FND(part):
+   #
+   # Panasonic FN series, size code D
+   #    100uF: EEE-FN1E101UL
+   #
+   def __init__(self,value=''):
+      pad = cube(-.032,.032,-.06,.06,0,0)
+      self.value = value
+      self.labels = []
+      self.pad = [point(0,0,0)]
+      self.shape = translate(pad,0,.11,0)
+      self.pad.append(point(0,.11,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'+',angle=90))
+      self.shape = add(self.shape,translate(pad,0,-.11,0))
+      self.pad.append(point(0,-.11,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'-',angle=90))
+
+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
+############################################################
+
+class header_2H(part):
+   #
+   # 2x1x0.1 cable header
+   #    Sullins GEC36SBSN-M89
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_header,0,.05,0)
+      self.pad.append(point(0,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.05,0))
+      self.pad.append(point(0,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'2'))
+
+class header_4H(part):
+   #
+   # 4x1x0.1 cable header
+   #    Sullins GEC36SBSN-M89
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_header,0,.15,0)
+      self.pad.append(point(0,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.05,0))
+      self.pad.append(point(0,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'2'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.05,0))
+      self.pad.append(point(0,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'3'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-0.15,0))
+      self.pad.append(point(0,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'4'))
+
+class header_NEO_6M(part):
+   #
+   # NEO_6M GPS module
+   #
+   def __init__(self,value=''):
+      pad_header = cylinder(0,0,0,0,.03)
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_header,0,.2,0)
+      self.pad.append(point(0,.2,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PPS'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.1,0))
+      self.pad.append(point(0,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'TXD'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_header,0,0,0))
+      self.pad.append(point(0,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RXD'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.1,0))
+      self.pad.append(point(0,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.2,0))
+      self.pad.append(point(0,-.2,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC'))
+
+class header_MFRC522(part):
+   #
+   # MFCR522 RFID module
+   #
+   def __init__(self,value=''):
+      pad_header = cylinder(0,0,0,0,.03)
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_header,0,.35,0)
+      self.pad.append(point(0,.35,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1SDA'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.25,0))
+      self.pad.append(point(0,.25,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCK'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.15,0))
+      self.pad.append(point(0,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'COPI'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_header,0,0.05,0))
+      self.pad.append(point(0,0.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CIPO'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.05,0))
+      self.pad.append(point(0,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IRQ'))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.15,0))
+      self.pad.append(point(0,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.25,0))
+      self.pad.append(point(0,-.25,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RST'))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.35,0))
+      self.pad.append(point(0,-.35,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'3.3V'))
+
+class header_LSM6DS33_2736(part):
+   #
+   # LSD6DS33 carrier
+   #    Pololu 2736
+   #
+   def __init__(self,value=''):
+      pad_header = cylinder(0,0,0,0,.03)
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_header,0,.4,0)
+      self.pad.append(point(0,.4,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1VDD'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.3,0))
+      self.pad.append(point(0,.3,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VIN'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.2,0))
+      self.pad.append(point(0,.2,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_header,0,0.1,0))
+      self.pad.append(point(0,0.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SDA'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad_header,0,0,0))
+      self.pad.append(point(0,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCL'))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.1,0))
+      self.pad.append(point(0,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SDO'))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.2,0))
+      self.pad.append(point(0,-.2,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CS'))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.3,0))
+      self.pad.append(point(0,-.3,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'INT2'))
+      #
+      # pin 9
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.4,0))
+      self.pad.append(point(0,-.4,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'INT1'))
+
+class header_VL53L1X_3415(part):
+   #
+   # VL53L1X carrier
+   #    Pololu 3415
+   #
+   def __init__(self,value=''):
+      pad_header = cylinder(0,0,0,0,.03)
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_header,0,.3,0)
+      self.pad.append(point(0,.3,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1VDD'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.2,0))
+      self.pad.append(point(0,.2,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VIN'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.1,0))
+      self.pad.append(point(0,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_header,0,0,0))
+      self.pad.append(point(0,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SDA'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.1,0))
+      self.pad.append(point(0,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCL'))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.2,0))
+      self.pad.append(point(0,-.2,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'XSHUT'))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.3,0))
+      self.pad.append(point(0,-.3,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GPIO1'))
+
+class ESP_WROOM_02D(part):
+   #
+   # ESP-WROOM-02D
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      pad = cube(-1/25.4,1/25.4,-.45/25.4,.45/25.4,0,0)
+      width = 17.5/25.4
+      pitch = 1.5/25.4
+      #
+      # pin 1
+      #
+      self.shape = translate(pad,-width/2,4*pitch,0)
+      self.shape = add(self.shape,cylinder(-width/2-.75/25.4,4*pitch,0,0,.45/25.4))
+      self.pad.append(point(-width/2,4*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'3V3'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,3*pitch,0))
+      self.pad.append(point(-width/2,3*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'EN'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,2*pitch,0))
+      self.pad.append(point(-width/2,2*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO14'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,1*pitch,0))
+      self.pad.append(point(-width/2,1*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO12'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,0*pitch,0))
+      self.pad.append(point(-width/2,0*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO13'))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,-1*pitch,0))
+      self.pad.append(point(-width/2,-1*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO15'))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,-2*pitch,0))
+      self.pad.append(point(-width/2,-2*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO2'))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,-3*pitch,0))
+      self.pad.append(point(-width/2,-3*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO0'))
+      #
+      # pin 9
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,-4*pitch,0))
+      self.pad.append(point(-width/2,-4*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 10
+      #
+      self.shape = add(self.shape,translate(pad,width/2,-4*pitch,0))
+      self.pad.append(point(width/2,-4*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO4'))
+      #
+      # pin 11
+      #
+      self.shape = add(self.shape,translate(pad,width/2,-3*pitch,0))
+      self.pad.append(point(width/2,-3*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RXD'))
+      #
+      # pin 12
+      #
+      self.shape = add(self.shape,translate(pad,width/2,-2*pitch,0))
+      self.pad.append(point(width/2,-2*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'TXD'))
+      #
+      # pin 13
+      #
+      self.shape = add(self.shape,translate(pad,width/2,-1*pitch,0))
+      self.pad.append(point(width/2,-1*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 14
+      #
+      self.shape = add(self.shape,translate(pad,width/2,0*pitch,0))
+      self.pad.append(point(width/2,0*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO5'))
+      #
+      # pin 15
+      #
+      self.shape = add(self.shape,translate(pad,width/2,1*pitch,0))
+      self.pad.append(point(width/2,1*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RST'))
+      #
+      # pin 16
+      #
+      self.shape = add(self.shape,translate(pad,width/2,2*pitch,0))
+      self.pad.append(point(width/2,2*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'TOUT'))
+      #
+      # pin 17
+      #
+      self.shape = add(self.shape,translate(pad,width/2,3*pitch,0))
+      self.pad.append(point(width/2,3*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO16'))
+      #
+      # pin 18
+      #
+      self.shape = add(self.shape,translate(pad,width/2,4*pitch,0))
+      self.pad.append(point(width/2,4*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 19
+      #
+      padg = cube(-2/25.4,2/25.4,-2/25.4,2/25.4,0,0)
+      self.shape = add(self.shape,translate(padg,(1.5/2+7.1+2-17.5/2)/25.4,(4*1.5+7.1-20+4.29+2)/25.4,0))
+      self.pad.append(point((1.5/2+7.1+2-17.5/2)/25.4,(4*1.5+7.1-20+4.29+2)/25.4,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+
+class ESP_01(part):
+   #
+   # ESP-01 4x2 vertical
+   #    Sullins NPTC042KFMS-RC
+   #
+   def __init__(self,value=''):
+      pad_header = cube(-.075/2,.075/2,-.04/2,.04/2,0,0)
+      d = .305/2-.07/2
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_header,d,.15,0)
+      self.shape = add(self.shape,cylinder(d+.061/2,.15,0,0,.039/2))
+      self.pad.append(point(d,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,-d,.15,0))
+      self.pad.append(point(-d,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Tx'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_header,d,.05,0))
+      self.pad.append(point(d,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO2'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_header,-d,.05,0))
+      self.pad.append(point(-d,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'EN'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad_header,d,-.05,0))
+      self.pad.append(point(d,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO0'))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad_header,-d,-.05,0))
+      self.pad.append(point(-d,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RST'))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad_header,d,-.15,0))
+      self.pad.append(point(d,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Rx'))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(pad_header,-d,-.15,0))
+      self.pad.append(point(-d,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC'))
+
+class header_serial_reverse_5V(part):
+   #
+   # serial cable header, reverse for female connector, 5V output
+   #    GCT BG300-06-A-L-A
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_header,0,-.25,0)
+      self.shape = add(self.shape,cylinder(-.05,-.25,0,0,.025))
+      self.pad.append(point(0,-.25,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.15,0))
+      self.pad.append(point(0,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CTS'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.05,0))
+      self.pad.append(point(0,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'5V'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_header,0,0.05,0))
+      self.pad.append(point(0,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Tx'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.15,0))
+      self.pad.append(point(0,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Rx'))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.25,0))
+      self.pad.append(point(0,.25,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RTS'))
+
+class header_serial_reverse_3V3(part):
+   #
+   # serial cable header, reverse for female connector, 3.3V output
+   #    GCT BG300-06-A-L-A
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_header,0,-.25,0)
+      self.shape = add(self.shape,cylinder(-.05,-.25,0,0,.025))
+      self.pad.append(point(0,-.25,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.15,0))
+      self.pad.append(point(0,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CTS'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.05,0))
+      self.pad.append(point(0,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'3.3V'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_header,0,0.05,0))
+      self.pad.append(point(0,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Tx'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.15,0))
+      self.pad.append(point(0,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Rx'))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.25,0))
+      self.pad.append(point(0,.25,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RTS'))
+
+class TFT8x1v(part):
+   #
+   # TFT 8x1 vertical
+   #    2x Sullins S5635-ND
+   #
+   def __init__(self,value=''):
+      pad_header = cube(-.079/2,.079/2,-.039/2,.039/2,0,0)
+      d = .209/2-.079/2
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_header,-d,-.35,0)
+      self.pad.append(point(-d,-.35,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1LED'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,d,-.25,0))
+      self.pad.append(point(d,-.25,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCK'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_header,-d,-.15,0))
+      self.pad.append(point(-d,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'MOSI'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_header,d,-.05,0))
+      self.pad.append(point(d,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DC'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad_header,-d,.05,0))
+      self.pad.append(point(-d,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RST'))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad_header,d,.15,0))
+      self.pad.append(point(d,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CS'))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad_header,-d,.25,0))
+      self.pad.append(point(-d,.25,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(pad_header,d,.35,0))
+      self.pad.append(point(d,.35,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC'))
+
+class header_SWD_4_05(part):
+   #
+   # 4-pin header
+   # Sullins GRPB022VWQS-RC 2x2x0.05"
+   #
+   def __init__(self,value=''):
+      pad_header = cube(-.043,.043,-.015,.015,0,0)
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_header,-.072,.025,0)
+      self.shape = add(self.shape,cylinder(-.116,.025,0,0,.015))
+      self.pad.append(point(-.072,.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CLK'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,.072,.025,0))
+      self.pad.append(point(.072,.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DIO'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_header,-.072,-.025,0))
+      self.pad.append(point(-.072,-.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RST'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_header,.072,-.025,0))
+      self.pad.append(point(.072,-.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+
+class header_SWD_4_1(part):
+   #
+   # 4-pin header
+   # FCI 95278-101a04lf Bergstik 2x2x0.1"
+   #
+   pad_header = cube(-.05,.05,-.025,.025,0,0)
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_header,-.107,.05,0)
+      #self.shape = add(self.shape,cylinder(-.157,.05,0,0,.025))
+      self.pad.append(point(-.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CLK'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.05,0))
+      self.pad.append(point(.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DIO'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.05,0))
+      self.pad.append(point(-.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RST'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,-.05,0))
+      self.pad.append(point(.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+
+class header_UPDI(part):
+   #
+   # UPDI header
+   #    Sullins GEC36SBSN-M89
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: UPDI
+      #
+      self.shape = translate(pad_header,0,-.05,0)
+      self.shape = add(self.shape,cylinder(.05,-.05,0,0,.025))
+      self.pad.append(point(0,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'UPDI'))
+      #
+      # pin 2: GND
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.05,0))
+      self.pad.append(point(0,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+
+class header_UPDI_reverse(part):
+   #
+   # UPDI header, reverse for female connector
+   #    GCT BG300-03-A-L-A
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: UPDI
+      #
+      self.shape = translate(pad_header,0,.05,0)
+      self.shape = add(self.shape,cylinder(.05,.05,0,0,.025))
+      self.pad.append(point(0,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'UPDI'))
+      #
+      # pin 2: GND
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.05,0))
+      self.pad.append(point(0,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+
+class USB_A_plug(part):
+   #
+   # USB type A PCB plug
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: 5V
+      #
+      self.shape = translate(cube(-.05,.242,-.02,.02,0,0),0,.138,0)
+      self.pad.append(point(0,.138,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'5V'))
+      #
+      # pin 2: D-
+      #
+      self.shape = add(self.shape,translate(cube(-0.05,.202,-.02,.02,0,0),0,.039,0))
+      self.pad.append(point(0,.039,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'D-'))
+      #
+      # pin 3: D+
+      #
+      self.shape = add(self.shape,translate(cube(-.05,.202,-.02,.02,0,0),0,-.039,0))
+      self.pad.append(point(0,-.039,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'D+'))
+      #
+      # pin 4: GND
+      #
+      self.shape = add(self.shape,translate(cube(-.05,.242,-.02,.02,0,0),0,-.138,0))
+      self.pad.append(point(0,-.138,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # plug cutout
+      #
+      self.cutout = cube(-.05,1,.24,10,zb,zt)
+      self.cutout = add(self.cutout,cube(-.05,10,-10,-.24,zb,zt))
+
+class header_SWD(part):
+   #
+   # Serial Wire Debug programming header
+   # Amphenol 20021121-00010T1LF	2x5x0.05
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      d = 0.077
+      w = 0.015
+      h = .047
+      pad = cube(-h,h,-w,w,0,0)
+      #
+      # pin 1: VCC
+      #
+      self.shape = translate(pad,d,-.1,0)
+      self.shape = add(self.shape,cylinder(d+h,-.1,0,0,w))
+      self.pad.append(point(d,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC'))
+      #
+      # pin 2: DIO
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.1,0))
+      self.pad.append(point(-d,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DIO'))
+      #
+      # pin 3: GND
+      #
+      self.shape = add(self.shape,translate(pad,d,-.05,0))
+      self.pad.append(point(d,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 4: CLK
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.05,0))
+      self.pad.append(point(-d,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CLK'))
+      #
+      # pin 5: GND
+      #
+      self.shape = add(self.shape,translate(pad,d,0,0))
+      self.pad.append(point(d,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 6: SWO
+      #
+      self.shape = add(self.shape,translate(pad,-d,0,0))
+      self.pad.append(point(-d,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SWO'))
+      #
+      # pin 7: KEY
+      #
+      self.shape = add(self.shape,translate(pad,d,.05,0))
+      self.pad.append(point(d,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'KEY'))
+      #
+      # pin 8: NC
+      #
+      self.shape = add(self.shape,translate(pad,-d,.05,0))
+      self.pad.append(point(-d,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'NC'))
+      #
+      # pin 9: GND
+      #
+      self.shape = add(self.shape,translate(pad,d,.1,0))
+      self.pad.append(point(d,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 10: nRESET
+      #
+      self.shape = add(self.shape,translate(pad,-d,.1,0))
+      self.pad.append(point(-d,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RST'))
+
+class ESC(part):
+   #
+   # ESC 3x1
+   # Sullins S1013E-36-ND
+   #
+   def __init__(self,value=''):
+      pad_header = cube(-.1,.1,-.05/2,.05/2,0,0)
+      d = .075
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: PWM
+      #
+      self.shape = translate(pad_header,-d,-.1,0)
+      self.pad.append(point(-d,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PWM'))
+      #
+      # pin 2: 5V
+      #
+      self.shape = add(self.shape,translate(pad_header,d,0,0))
+      self.pad.append(point(d,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'5V'))
+      #
+      # pin 3: GND
+      #
+      self.shape = add(self.shape,translate(pad_header,-d,.1,0))
+      self.pad.append(point(-d,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+
+class I2C4x1h(part):
+   #
+   # I2C 4x1 horizontal female
+   #    GCT BG300-03-A-L-A
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: SCL
+      #
+      self.shape = translate(pad_header,0,-.15,0)
+      #self.shape = cylinder(.05,.15,0,0,.025)
+      self.pad.append(point(0,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCL'))
+      #
+      # pin 2: SDA
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.05,0))
+      self.pad.append(point(0,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SDA'))
+      #
+      # pin 3: VCC
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.05,0))
+      self.pad.append(point(0,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC'))
+      #
+      # pin 4: GND
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.15,0))
+      self.pad.append(point(0,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+
+class I2C4x1v(part):
+   #
+   # I2C 4x1 vertical
+   #    Sullins S5635-ND
+   #
+   def __init__(self,value=''):
+      pad_header = cube(-.079/2,.079/2,-.039/2,.039/2,0,0)
+      d = .209/2-.079/2
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: VCC
+      #
+      self.shape = translate(pad_header,-d,-.15,0)
+      self.pad.append(point(-d,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1VCC'))
+      #
+      # pin 2: GND
+      #
+      self.shape = add(self.shape,translate(pad_header,d,-.05,0))
+      self.pad.append(point(d,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 3: SCL
+      #
+      self.shape = add(self.shape,translate(pad_header,-d,.05,0))
+      self.pad.append(point(-d,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCL'))
+      #
+      # pin 4: SDA
+      #
+      self.shape = add(self.shape,translate(pad_header,d,.15,0))
+      self.pad.append(point(d,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SDA'))
+
+class I2C4x1i(part):
+   #
+   # I2C 4x1 inline
+   #
+   def __init__(self,value=''):
+      pad_header = cube(-.079/2,.079/2,-.039/2,.039/2,0,0)
+      d = 0
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: VCC
+      #
+      self.shape = translate(pad_header,-d,-.15,0)
+      self.pad.append(point(-d,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1VCC'))
+      #
+      # pin 2: GND
+      #
+      self.shape = add(self.shape,translate(pad_header,d,-.05,0))
+      self.pad.append(point(d,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 3: SCL
+      #
+      self.shape = add(self.shape,translate(pad_header,-d,.05,0))
+      self.pad.append(point(-d,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCL'))
+      #
+      # pin 4: SDA
+      #
+      self.shape = add(self.shape,translate(pad_header,d,.15,0))
+      self.pad.append(point(d,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SDA'))
+
+class RCWL0516(part):
+   #
+   # RCWL-0516 Doppler radar
+   #
+   def __init__(self,value=''):
+      pad_header = cube(-.065,.065,-.025,.025,0,0)
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: 3.3V
+      #
+      self.shape = translate(pad_header,.107,-.2,0)
+      self.shape = add(self.shape,cylinder(.172,-.2,0,0,.025))
+      self.pad.append(point(.107,-.2,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'3.3V'))
+      #
+      # pin 2: GND
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.1,0))
+      self.pad.append(point(-.107,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 3: OUT
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,0,0))
+      self.pad.append(point(.107,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'OUT'))
+      #
+      # pin 4: VIN
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,.1,0))
+      self.pad.append(point(-.107,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VIN'))
+      #
+      # pin 5: CDS
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.2,0))
+      self.pad.append(point(.107,.2,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CDS'))
+
+class microSD(part):
+   #
+   # microSD
+   # Amphenol 114-00841-68
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(cube(-.0138,.0138,-.034,.034,0,0),-.177+7*.0433,-.304,0)
+      self.pad.append(point(-.177+7*.0433,-.304,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1NC',angle=90))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(cube(-.0138,.0138,-.034,.034,0,0),-.177+6*.0433,-.304,0))
+      self.pad.append(point(-.177+6*.0433,-.304,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SS',angle=90))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(cube(-.0138,.0138,-.034,.034,0,0),-.177+5*.0433,-.304,0))
+      self.pad.append(point(-.177+5*.0433,-.304,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'MOSI',angle=90))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(cube(-.0138,.0138,-.034,.034,0,0),-.177+4*.0433,-.304,0))
+      self.pad.append(point(-.177+4*.0433,-.304,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC',angle=90))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(cube(-.0138,.0138,-.034,.034,0,0),-.177+3*.0433,-.304,0))
+      self.pad.append(point(-.177+3*.0433,-.304,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCK',angle=90))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(cube(-.0138,.0138,-.034,.034,0,0),-.177+2*.0433,-.304,0))
+      self.pad.append(point(-.177+2*.0433,-.304,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',angle=90))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(cube(-.0138,.0138,-.034,.034,0,0),-.177+1*.0433,-.304,0))
+      self.pad.append(point(-.177+1*.0433,-.304,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'MISO',angle=90))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(cube(-.0138,.0138,-.034,.034,0,0),-.177+0*.0433,-.304,0))
+      self.pad.append(point(-.177+0*.0433,-.304,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'NC',angle=90))
+      #
+      # feet
+      #
+      self.shape = add(self.shape,translate(cube(-.021,.021,-.029,.029,0,0),-.228,-.299,0)) # leave extra space for 1/64 milling
+      self.shape = add(self.shape,translate(cube(-.029,.029,-.029,.029,0,0),.222,-.299,0))
+      self.shape = add(self.shape,translate(cube(-.015,.015,-.029,.025,0,0),-.232,0,0)) # leave extra space for 1/64 milling
+      self.shape = add(self.shape,translate(cube(-.015,.015,-.029,.029,0,0),-.232+.47,.025,0))
+      self.shape = add(self.shape,translate(cube(-.028,.028,-.019,.019,0,0),-.221,.059,0))
+      self.shape = add(self.shape,translate(cube(-.019,.019,-.030,.030,0,0),.222,.121,0))
+
+pad_USB_trace = cube(-.0075,.0075,-.04,.04,0,0)
+pad_USB_feet = cube(-.049,.049,-.043,.043,0,0)
+
+class USB_mini_B(part):
+   #
+   # USB mini B
+   # Hirose UX60-MB-5ST
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_USB_trace,.063,.36,0)
+      self.pad.append(point(.063,.36,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_USB_trace,.0315,.36,0))
+      self.pad.append(point(.0315,.36,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,''))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_USB_trace,0,.36,0))
+      self.pad.append(point(0,.36,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'+'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_USB_trace,-.0315,.36,0))
+      self.pad.append(point(-.0315,.36,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'-'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad_USB_trace,-.063,.36,0))
+      self.pad.append(point(-.063,.36,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V'))
+      #
+      # feet
+      #
+      self.shape = add(self.shape,translate(pad_USB_feet,.165,.33,0))
+      self.shape = add(self.shape,translate(pad_USB_feet,-.165,.33,0))
+      self.shape = add(self.shape,translate(pad_USB_feet,.165,.12,0))
+      self.shape = add(self.shape,translate(pad_USB_feet,-.165,.12,0))
+
+pad_header = cube(-.05,.05,-.025,.025,0,0)
+
+class header_4(part):
+   #
+   # 4-pin header
+   # fci 95278-101a04lf bergstik 2x2x0.1"
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_header,-.107,.05,0)
+      self.shape = add(self.shape,cylinder(-.157,.05,0,0,.025))
+      self.pad.append(point(-.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.05,0))
+      self.pad.append(point(.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'2'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.05,0))
+      self.pad.append(point(-.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'3'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,-.05,0))
+      self.pad.append(point(.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'4'))
+
+class header_signal(part):
+   #
+   # signal header
+   # FCI 95278-101A04LF Bergstik 2x2x0.1"
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: Gnd
+      #
+      self.shape = translate(pad_header,.107,-.05,0)
+      self.shape = add(self.shape,cylinder(.157,-.05,0,0,.025))
+      self.pad.append(point(.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.05,0))
+      self.pad.append(point(-.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,''))
+      #
+      # pin 3: signal
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.05,0))
+      self.pad.append(point(.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'signal'))
+      #
+      # pin 4:
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,.05,0))
+      self.pad.append(point(-.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,''))
+
+
+class header_power(part):
+   #
+   # power header
+   # FCI 95278-101A04LF Bergstik 2x2x0.1"
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: Gnd
+      #
+      self.shape = translate(pad_header,.107,-.05,0)
+      self.shape = add(self.shape,cylinder(.157,-.05,0,0,.025))
+      self.pad.append(point(.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.05,0))
+      self.pad.append(point(-.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,''))
+      #
+      # pin 3: V
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.05,0))
+      self.pad.append(point(.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V'))
+      #
+      # pin 4:
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,.05,0))
+      self.pad.append(point(-.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,''))
+
+class header_i0(part):
+   #
+   # i0 header
+   # FCI 95278-101A04LF Bergstik 2x2x0.1"
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: Gnd
+      #
+      self.shape = translate(pad_header,.107,-.05,0)
+      self.shape = add(self.shape,cylinder(.157,-.05,0,0,.025))
+      self.pad.append(point(.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 2: data
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.05,0))
+      self.pad.append(point(-.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'data'))
+      #
+      # pin 3: V
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.05,0))
+      self.pad.append(point(.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V'))
+      #
+      # pin 4:
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,.05,0))
+      self.pad.append(point(-.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,''))
+
+class header_serial(part):
+   #
+   # serial comm header
+   # FCI 95278-101A04LF Bergstik 2x2x0.1"
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: Gnd
+      #
+      self.shape = translate(pad_header,.107,-.05,0)
+      self.shape = add(self.shape,cylinder(.157,-.05,0,0,.025))
+      self.pad.append(point(.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 2:DTR
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.05,0))
+      self.pad.append(point(-.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DTR'))
+      #
+      # pin 3: Tx
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.05,0))
+      self.pad.append(point(.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Tx'))
+      #
+      # pin 4: Rx
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,.05,0))
+      self.pad.append(point(-.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Rx'))
+
+class header_bus(part):
+   #
+   # bus header
+   # FCI 95278-101A04LF Bergstik 2x2x0.1"
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: Gnd
+      #
+      self.shape = translate(pad_header,.107,-.05,0)
+      self.shape = add(self.shape,cylinder(.157,-.05,0,0,.025))
+      self.pad.append(point(.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 2: Tx
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.05,0))
+      self.pad.append(point(-.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Tx'))
+      #
+      # pin 3: V
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.05,0))
+      self.pad.append(point(.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V'))
+      #
+      # pin 4: Rx
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,.05,0))
+      self.pad.append(point(-.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Rx'))
+
+class header_I2C(part):
+   #
+   # I2C header
+   # FCI 95278-101A04LF Bergstik 2x2x0.1"
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: SCL
+      #
+      self.shape = translate(pad_header,.107,-.05,0)
+      self.shape = add(self.shape,cylinder(.157,-.05,0,0,.025))
+      self.pad.append(point(.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCL'))
+      #
+      # pin 2: G
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.05,0))
+      self.pad.append(point(-.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G'))
+      #
+      # pin 3: SDA
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.05,0))
+      self.pad.append(point(.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SDA'))
+      #
+      # pin 4: V
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,.05,0))
+      self.pad.append(point(-.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V'))
+
+class header_APA(part):
+   #
+   # APA header
+   # FCI 95278-101A04LF Bergstik 2x2x0.1"
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: Gnd
+      #
+      self.shape = translate(pad_header,.107,-.05,0)
+      self.shape = add(self.shape,cylinder(.157,-.05,0,0,.025))
+      self.pad.append(point(.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 2: in
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.05,0))
+      self.pad.append(point(-.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'in'))
+      #
+      # pin 3: V
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.05,0))
+      self.pad.append(point(.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V'))
+      #
+      # pin 4: out
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,.05,0))
+      self.pad.append(point(-.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'out'))
+
+class header_6(part):
+   #
+   # 6-pin header
+   # FCI 95278-101A06LF Bergstik 2x3x0.1"
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_header,.107,-.1,0)
+      self.shape = add(self.shape,cylinder(.157,-.1,0,0,.025))
+      self.pad.append(point(.107,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,''))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.1,0))
+      self.pad.append(point(-.107,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,''))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,0,0))
+      self.pad.append(point(.107,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,''))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,0,0))
+      self.pad.append(point(-.107,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,''))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.1,0))
+      self.pad.append(point(.107,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,''))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,.1,0))
+      self.pad.append(point(-.107,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,''))
+
+class header_ATP(part):
+   #
+   # Asynchronous Token Protocol header
+   # FCI 95278-101A06LF Bergstik 2x3x0.1"
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_header,.107,-.1,0)
+      self.shape = add(self.shape,cylinder(.157,-.1,0,0,.025))
+      self.pad.append(point(.107,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'BI'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.1,0))
+      self.pad.append(point(-.107,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'TI'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,0,0))
+      self.pad.append(point(.107,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,0,0))
+      self.pad.append(point(-.107,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.1,0))
+      self.pad.append(point(.107,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'TO'))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,.1,0))
+      self.pad.append(point(-.107,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'BO'))
+
+class header_PDI(part):
+   #
+   # in-circuit PDI programming header
+   # FCI 95278-101A06LF Bergstik 2x3x0.1"
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: Data
+      #
+      self.shape = translate(pad_header,.107,-.1,0)
+      self.shape = add(self.shape,cylinder(.157,-.1,0,0,.025))
+      self.pad.append(point(.107,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DAT'))
+      #
+      # pin 2: VCC
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.1,0))
+      self.pad.append(point(-.107,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC'))
+      #
+      # pin 3: NC
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,0,0))
+      self.pad.append(point(.107,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'NC'))
+      #
+      # pin 4: NC
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,0,0))
+      self.pad.append(point(-.107,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'NC'))
+      #
+      # pin 5: Clock
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.1,0))
+      self.pad.append(point(.107,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CLK'))
+      #
+      # pin 6: GND
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,.1,0))
+      self.pad.append(point(-.107,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+
+class header_ISP(part):
+   #
+   # in-circuit ISP programming header
+   # FCI 95278-101A06LF Bergstik 2x3x0.1"
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: MISO
+      #
+      self.shape = translate(pad_header,.107,-.1,0)
+      self.shape = add(self.shape,cylinder(.157,-.1,0,0,.025))
+      self.pad.append(point(.107,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'MISO'))
+      #
+      # pin 2: V
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.1,0))
+      self.pad.append(point(-.107,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V'))
+      #
+      # pin 3: SCK
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,0,0))
+      self.pad.append(point(.107,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCK'))
+      #
+      # pin 4: MOSI
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,0,0))
+      self.pad.append(point(-.107,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'MOSI'))
+      #
+      # pin 5: RST
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.1,0))
+      self.pad.append(point(.107,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RST'))
+      #
+      # pin 6: GND
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,.1,0))
+      self.pad.append(point(-.107,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+
+class header_nRF24L01(part):
+   #
+   # nRF24L01 module header
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1:
+      #
+      self.shape = translate(pad_header,.107,-.15,0)
+      self.shape = add(self.shape,cylinder(.157,-.15,0,0,.025))
+      self.pad.append(point(.107,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 2:
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.15,0))
+      self.pad.append(point(-.107,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC'))
+      #
+      # pin 3:
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,-.05,0))
+      self.pad.append(point(.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CE'))
+      #
+      # pin 4:
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.05,0))
+      self.pad.append(point(-.107,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CS'))
+      #
+      # pin 5:
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.05,0))
+      self.pad.append(point(.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCK'))
+      #
+      # pin 6:
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,.05,0))
+      self.pad.append(point(-.107,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'MOSI'))
+      #
+      # pin 7:
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.15,0))
+      self.pad.append(point(.107,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'MISO'))
+      #
+      # pin 8:
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,.15,0))
+      self.pad.append(point(-.107,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IRQ'))
+
+class header_servo(part):
+   #
+   # servo motor header
+   # FCI 95278-101A06LF Bergstik 2x3x0.1"
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: ground
+      #
+      self.shape = translate(pad_header,.107,-.1,0)
+      self.shape = add(self.shape,cylinder(.157,-.1,0,0,.025))
+      self.pad.append(point(.107,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G/blk'))
+      #
+      # pin 2: ground
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.1,0))
+      self.pad.append(point(-.107,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G/blk'))
+      #
+      # pin 3: power
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,0,0))
+      self.pad.append(point(.107,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V/red'))
+      #
+      # pin 4: power
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,0,0))
+      self.pad.append(point(-.107,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V/red'))
+      #
+      # pin 5: signal 0
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.1,0))
+      self.pad.append(point(.107,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'S0/wht'))
+      #
+      # pin 6: signal 1
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,.1,0))
+      self.pad.append(point(-.107,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'S1/wht'))
+
+class header_unipolar_stepper(part):
+   #
+   # unipolar stepper header
+   # FCI 95278-101A06LF Bergstik 2x3x0.1"
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_header,.107,-.1,0)
+      self.shape = add(self.shape,cylinder(.157,-.1,0,0,.025))
+      self.pad.append(point(.107,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'red'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.1,0))
+      self.pad.append(point(-.107,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'green'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,0,0))
+      self.pad.append(point(.107,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'black'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,0,0))
+      self.pad.append(point(-.107,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'brown'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.1,0))
+      self.pad.append(point(.107,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'orange'))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,.1,0))
+      self.pad.append(point(-.107,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'yellow'))
+
+class header_LCD(part):
+   #
+   # LCD interface header
+   # FCI 95278-101A10LF Bergstik 2x3x0.1"
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1:
+      #
+      self.shape = translate(pad_header,.107,-.2,0)
+      self.shape = add(self.shape,cylinder(.157,-.2,0,0,.025))
+      self.pad.append(point(.107,-.2,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DB7\n14'))
+      #
+      # pin 2:
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.2,0))
+      self.pad.append(point(-.107,-.2,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DB6\n13'))
+      #
+      # pin 3:
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,-.1,0))
+      self.pad.append(point(.107,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DB5\n12'))
+      #
+      # pin 4:
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,-.1,0))
+      self.pad.append(point(-.107,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DB4\n11'))
+      #
+      # pin 5:
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,0,0))
+      self.pad.append(point(.107,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'E\n6'))
+      #
+      # pin 6:
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,0,0))
+      self.pad.append(point(-.107,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'R/W\n5'))
+      #
+      # pin 7:
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.1,0))
+      self.pad.append(point(.107,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RS\n4'))
+      #
+      # pin 8:
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,.1,0))
+      self.pad.append(point(-.107,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Vee\n3'))
+      #
+      # pin 9:
+      #
+      self.shape = add(self.shape,translate(pad_header,.107,.2,0))
+      self.pad.append(point(.107,.2,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Vcc\n2'))
+      #
+      # pin 10:
+      #
+      self.shape = add(self.shape,translate(pad_header,-.107,.2,0))
+      self.pad.append(point(-.107,.2,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND\n1'))
+
+class header_serial_reverse(part):
+   #
+   # serial cable header, reverse for female connector
+   #    GCT BG300-06-A-L-A
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: GND
+      #
+      self.shape = translate(pad_header,0,-.25,0)
+      self.shape = add(self.shape,cylinder(-.05,-.25,0,0,.025))
+      self.pad.append(point(0,-.25,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 2: CTS (brown)
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.15,0))
+      self.pad.append(point(0,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CTS'))
+      #
+      # pin 3: VCC (red)
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.05,0))
+      self.pad.append(point(0,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC'))
+      #
+      # pin 4: Tx (orange)
+      #
+      self.shape = add(self.shape,translate(pad_header,0,0.05,0))
+      self.pad.append(point(0,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Tx'))
+      #
+      # pin 5: Rx (yellow)
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.15,0))
+      self.pad.append(point(0,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Rx'))
+      #
+      # pin 6: RTS (green)
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.25,0))
+      self.pad.append(point(0,.25,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RTS'))
+
+class header_FTDI(part):
+   #
+   # FTDI cable header
+   #    Sullins GEC36SBSN-M89
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: GND
+      #
+      self.shape = translate(pad_header,0,.25,0)
+      self.shape = add(self.shape,cylinder(-.05,.25,0,0,.025))
+      self.pad.append(point(0,.25,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 2: CTS (brown)
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.15,0))
+      self.pad.append(point(0,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CTS'))
+      #
+      # pin 3: VCC (red)
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.05,0))
+      self.pad.append(point(0,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC'))
+      #
+      # pin 4: Tx (orange)
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-0.05,0))
+      self.pad.append(point(0,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Tx'))
+      #
+      # pin 5: Rx (yellow)
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.15,0))
+      self.pad.append(point(0,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Rx'))
+      #
+      # pin 6: RTS (green)
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.25,0))
+      self.pad.append(point(0,-.25,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RTS'))
+
+class HCSR04(part):
+   #
+   # HC-SR04 sonar header
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: GND
+      #
+      self.shape = translate(pad_header,0,.15,0)
+      self.shape = add(self.shape,cylinder(-.05,.15,0,0,.025))
+      self.pad.append(point(0,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 2: echo
+      #
+      self.shape = add(self.shape,translate(pad_header,0,.05,0))
+      self.pad.append(point(0,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'echo'))
+      #
+      # pin 3: trig
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.05,0))
+      self.pad.append(point(0,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'trig'))
+      #
+      # pin 4: Vcc
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-0.15,0))
+      self.pad.append(point(0,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Vcc'))
+
+class HCSR501(part):
+   #
+   # HC-SR501 motion detector header
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: Vcc
+      #
+      self.shape = translate(pad_header,0,.1,0)
+      self.shape = add(self.shape,cylinder(-.05,.1,0,0,.025))
+      self.pad.append(point(0,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Vcc'))
+      #
+      # pin 2: out
+      #
+      self.shape = add(self.shape,translate(pad_header,0,0,0))
+      self.pad.append(point(0,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'out'))
+      #
+      # pin 3: GND
+      #
+      self.shape = add(self.shape,translate(pad_header,0,-.1,0))
+      self.pad.append(point(0,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+
+pad_RN4871_left = cube(-0.5/25.4,1/25.4,-0.7/2/25.4,0.7/2/25.4,0,0)
+pad_RN4871_right = cube(-1/25.4,0.5/25.4,-0.7/2/25.4,0.7/2/25.4,0,0)
+pad_RN4871_bot = cube(-0.7/2/25.4,0.7/2/25.4,-0.5/25.4,1/25.4,0,0)
+
+class RN4871(part):
+   #
+   # RN4871
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      width = 9/25.4
+      height = 7.5/25.4
+      bottom = 1.9/25.4
+      left = 1.5/25.4
+      pitch = 1.2/25.4
+      size = .004
+      #
+      # pin 1:
+      #
+      self.shape = translate(pad_RN4871_left,-width/2.0,-height+bottom+4*pitch,0)
+      self.pad.append(point(-width/2.0,-height+bottom+4*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'BT_RF',line=size))
+      #
+      # pin 2:
+      #
+      self.shape = add(self.shape,translate(pad_RN4871_left,-width/2.0,-height+bottom+3*pitch,0))
+      self.pad.append(point(-width/2.0,-height+bottom+3*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=size))
+      #
+      # pin 3:
+      #
+      self.shape = add(self.shape,translate(pad_RN4871_left,-width/2.0,-height+bottom+2*pitch,0))
+      self.pad.append(point(-width/2.0,-height+bottom+2*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'P1_2',line=size))
+      #
+      # pin 4:
+      #
+      self.shape = add(self.shape,translate(pad_RN4871_left,-width/2.0,-height+bottom+1*pitch,0))
+      self.pad.append(point(-width/2.0,-height+bottom+1*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'P1_3',line=size))
+      #
+      # pin 5:
+      #
+      self.shape = add(self.shape,translate(pad_RN4871_left,-width/2.0,-height+bottom+0*pitch,0))
+      self.pad.append(point(-width/2.0,-height+bottom+0*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'P1_7',line=size))
+      #
+      # pin 6:
+      #
+      self.shape = add(self.shape,translate(pad_RN4871_bot,-width/2.0+left+0*pitch,-height,0))
+      self.pad.append(point(-width/2.0+left+0*pitch,-height,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'P1_6',line=size,angle=90))
+      #
+      # pin 7:
+      #
+      self.shape = add(self.shape,translate(pad_RN4871_bot,-width/2.0+left+1*pitch,-height,0))
+      self.pad.append(point(-width/2.0+left+1*pitch,-height,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RX',line=size,angle=90))
+      #
+      # pin 8:
+      #
+      self.shape = add(self.shape,translate(pad_RN4871_bot,-width/2.0+left+2*pitch,-height,0))
+      self.pad.append(point(-width/2.0+left+2*pitch,-height,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'TX',line=size,angle=90))
+      #
+      # pin 9:
+      #
+      self.shape = add(self.shape,translate(pad_RN4871_bot,-width/2.0+left+3*pitch,-height,0))
+      self.pad.append(point(-width/2.0+left+3*pitch,-height,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'P3_6',line=size,angle=90))
+      #
+      # pin 10:
+      #
+      self.shape = add(self.shape,translate(pad_RN4871_bot,-width/2.0+left+4*pitch,-height,0))
+      self.pad.append(point(-width/2.0+left+4*pitch,-height,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RST_N',line=size,angle=90))
+      #
+      # pin 11:
+      #
+      self.shape = add(self.shape,translate(pad_RN4871_bot,-width/2.0+left+5*pitch,-height,0))
+      self.pad.append(point(-width/2.0+left+5*pitch,-height,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'P0_0',line=size,angle=90))
+      #
+      # pin 12:
+      #
+      self.shape = add(self.shape,translate(pad_RN4871_right,width/2.0,-height+bottom+0*pitch,0))
+      self.pad.append(point(width/2.0,-height+bottom+0*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'P0_2',line=size))
+      #
+      # pin 13:
+      #
+      self.shape = add(self.shape,translate(pad_RN4871_right,width/2.0,-height+bottom+1*pitch,0))
+      self.pad.append(point(width/2.0,-height+bottom+1*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=size))
+      #
+      # pin 14:
+      #
+      self.shape = add(self.shape,translate(pad_RN4871_right,width/2.0,-height+bottom+2*pitch,0))
+      self.pad.append(point(width/2.0,-height+bottom+2*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VBAT',line=size))
+      #
+      # pin 15:
+      #
+      self.shape = add(self.shape,translate(pad_RN4871_right,width/2.0,-height+bottom+3*pitch,0))
+      self.pad.append(point(width/2.0,-height+bottom+3*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'P2_7',line=size))
+      #
+      # pin 16:
+      #
+      self.shape = add(self.shape,translate(pad_RN4871_right,width/2.0,-height+bottom+4*pitch,0))
+      self.pad.append(point(width/2.0,-height+bottom+4*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'P2_0',line=size))
+
+pad_HM11 = cube(-.047,.047,-.0177,.0177,0,0)
+
+class HM11(part):
+   #
+   # HM-11
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      height = 18.5/25.4
+      width = 13.5/25.4
+      pitch = 1.5/25.4
+      bottom = 1/25.4
+      offset = 0
+      size = .004
+      #
+      # pin 1:
+      #
+      self.shape = translate(pad_HM11,-width/2.0+offset,-height/2.0+bottom+7*pitch,0)
+      self.pad.append(point(-width/2.0+offset,-height/2.0+bottom+7*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RTS',line=size))
+      #
+      # pin 2:
+      #
+      self.shape = add(self.shape,translate(pad_HM11,-width/2.0+offset,-height/2.0+bottom+6*pitch,0))
+      self.pad.append(point(-width/2.0+offset,-height/2.0+bottom+6*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'TX',line=size))
+      #
+      # pin 3:
+      #
+      self.shape = add(self.shape,translate(pad_HM11,-width/2.0+offset,-height/2.0+bottom+5*pitch,0))
+      self.pad.append(point(-width/2.0+offset,-height/2.0+bottom+5*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CTS',line=size))
+      #
+      # pin 4:
+      #
+      self.shape = add(self.shape,translate(pad_HM11,-width/2.0+offset,-height/2.0+bottom+4*pitch,0))
+      self.pad.append(point(-width/2.0+offset,-height/2.0+bottom+4*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RX',line=size))
+      #
+      # pin 5:
+      #
+      self.shape = add(self.shape,translate(pad_HM11,-width/2.0+offset,-height/2.0+bottom+3*pitch,0))
+      self.pad.append(point(-width/2.0+offset,-height/2.0+bottom+3*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'NC',line=size))
+      #
+      # pin 6:
+      #
+      self.shape = add(self.shape,translate(pad_HM11,-width/2.0+offset,-height/2.0+bottom+2*pitch,0))
+      self.pad.append(point(-width/2.0+offset,-height/2.0+bottom+2*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'NC',line=size))
+      #
+      # pin 7:
+      #
+      self.shape = add(self.shape,translate(pad_HM11,-width/2.0+offset,-height/2.0+bottom+1*pitch,0))
+      self.pad.append(point(-width/2.0+offset,-height/2.0+bottom+1*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'NC',line=size))
+      #
+      # pin 8:
+      #
+      self.shape = add(self.shape,translate(pad_HM11,-width/2.0+offset,-height/2.0+bottom+0*pitch,0))
+      self.pad.append(point(-width/2.0+offset,-height/2.0+bottom+0*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'NC',line=size))
+      #
+      # pin 9:
+      #
+      self.shape = add(self.shape,translate(pad_HM11,width/2.0-offset,-height/2.0+bottom+0*pitch,0))
+      self.pad.append(point(width/2.0-offset,-height/2.0+bottom+0*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC',line=size))
+      #
+      # pin 10:
+      #
+      self.shape = add(self.shape,translate(pad_HM11,width/2.0-offset,-height/2.0+bottom+1*pitch,0))
+      self.pad.append(point(width/2.0-offset,-height/2.0+bottom+1*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'NC',line=size))
+      #
+      # pin 11:
+      #
+      self.shape = add(self.shape,translate(pad_HM11,width/2.0-offset,-height/2.0+bottom+2*pitch,0))
+      self.pad.append(point(width/2.0-offset,-height/2.0+bottom+2*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RST',line=size))
+      #
+      # pin 12:
+      #
+      self.shape = add(self.shape,translate(pad_HM11,width/2.0-offset,-height/2.0+bottom+3*pitch,0))
+      self.pad.append(point(width/2.0-offset,-height/2.0+bottom+3*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=size))
+      #
+      # pin 13:
+      #
+      self.shape = add(self.shape,translate(pad_HM11,width/2.0-offset,-height/2.0+bottom+4*pitch,0))
+      self.pad.append(point(width/2.0-offset,-height/2.0+bottom+4*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO3',line=size))
+      #
+      # pin 14:
+      #
+      self.shape = add(self.shape,translate(pad_HM11,width/2.0-offset,-height/2.0+bottom+5*pitch,0))
+      self.pad.append(point(width/2.0-offset,-height/2.0+bottom+5*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO2',line=size))
+      #
+      # pin 15:
+      #
+      self.shape = add(self.shape,translate(pad_HM11,width/2.0-offset,-height/2.0+bottom+6*pitch,0))
+      self.pad.append(point(width/2.0-offset,-height/2.0+bottom+6*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO1',line=size))
+      #
+      # pin 16:
+      #
+      self.shape = add(self.shape,translate(pad_HM11,width/2.0-offset,-height/2.0+bottom+7*pitch,0))
+      self.pad.append(point(width/2.0-offset,-height/2.0+bottom+7*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO0',line=size))
+
+class ESP32_WROOM(part):
+   #
+   # ESP32-WROOM
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      pad = cube(-1/25.4,1/25.4,-.4/25.4,.4/25.4,0,0)
+      padb = cube(-.4/25.4,.4/25.4,-1/25.4,1/25.4,0,0)
+      width = 17/25.4
+      height = 25.5/25.4
+      pitch = 1.27/25.4
+      #
+      # pin 1
+      #
+      self.shape = translate(pad,-width/2,6*pitch,0)
+      self.pad.append(point(-width/2,6*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,5*pitch,0))
+      self.pad.append(point(-width/2,5*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'3V3'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,4*pitch,0))
+      self.pad.append(point(-width/2,4*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'EN'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,3*pitch,0))
+      self.pad.append(point(-width/2,3*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VP'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,2*pitch,0))
+      self.pad.append(point(-width/2,2*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VN'))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,1*pitch,0))
+      self.pad.append(point(-width/2,1*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO34'))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,0*pitch,0))
+      self.pad.append(point(-width/2,0*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO35'))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,-1*pitch,0))
+      self.pad.append(point(-width/2,-1*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO32'))
+      #
+      # pin 9
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,-2*pitch,0))
+      self.pad.append(point(-width/2,-2*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO33'))
+      #
+      # pin 10
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,-3*pitch,0))
+      self.pad.append(point(-width/2,-3*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO25'))
+      #
+      # pin 11
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,-4*pitch,0))
+      self.pad.append(point(-width/2,-4*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO26'))
+      #
+      # pin 12
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,-5*pitch,0))
+      self.pad.append(point(-width/2,-5*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO27'))
+      #
+      # pin 13
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,-6*pitch,0))
+      self.pad.append(point(-width/2,-6*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO14'))
+      #
+      # pin 14
+      #
+      self.shape = add(self.shape,translate(pad,-width/2,-7*pitch,0))
+      self.pad.append(point(-width/2,-7*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO12'))
+      #
+      # pin 15
+      #
+      self.shape = add(self.shape,translate(padb,-4.5*pitch,-7*pitch-1/25.4,0))
+      self.pad.append(point(-4.5*pitch,-7*pitch-1/25.4,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',angle=90))
+      #
+      # pin 16
+      #
+      self.shape = add(self.shape,translate(padb,-3.5*pitch,-7*pitch-1/25.4,0))
+      self.pad.append(point(-3.5*pitch,-7*pitch-1/25.4,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO13',angle=90))
+      #
+      # pin 17
+      #
+      self.shape = add(self.shape,translate(padb,-2.5*pitch,-7*pitch-1/25.4,0))
+      self.pad.append(point(-2.5*pitch,-7*pitch-1/25.4,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SHD',angle=90))
+      #
+      # pin 18
+      #
+      self.shape = add(self.shape,translate(padb,-1.5*pitch,-7*pitch-1/25.4,0))
+      self.pad.append(point(-1.5*pitch,-7*pitch-1/25.4,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SWP',angle=90))
+      #
+      # pin 19
+      #
+      self.shape = add(self.shape,translate(padb,-0.5*pitch,-7*pitch-1/25.4,0))
+      self.pad.append(point(-0.5*pitch,-7*pitch-1/25.4,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCS',angle=90))
+      #
+      # pin 20
+      #
+      self.shape = add(self.shape,translate(padb,0.5*pitch,-7*pitch-1/25.4,0))
+      self.pad.append(point(0.5*pitch,-7*pitch-1/25.4,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCK',angle=90))
+      #
+      # pin 21
+      #
+      self.shape = add(self.shape,translate(padb,1.5*pitch,-7*pitch-1/25.4,0))
+      self.pad.append(point(1.5*pitch,-7*pitch-1/25.4,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SDO',angle=90))
+      #
+      # pin 22
+      #
+      self.shape = add(self.shape,translate(padb,2.5*pitch,-7*pitch-1/25.4,0))
+      self.pad.append(point(2.5*pitch,-7*pitch-1/25.4,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SDI',angle=90))
+      #
+      # pin 23
+      #
+      self.shape = add(self.shape,translate(padb,3.5*pitch,-7*pitch-1/25.4,0))
+      self.pad.append(point(3.5*pitch,-7*pitch-1/25.4,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO15',angle=90))
+      #
+      # pin 24
+      #
+      self.shape = add(self.shape,translate(padb,4.5*pitch,-7*pitch-1/25.4,0))
+      self.pad.append(point(4.5*pitch,-7*pitch-1/25.4,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO2',angle=90))
+      #
+      # pin 25
+      #
+      self.shape = add(self.shape,translate(pad,width/2,-7*pitch,0))
+      self.pad.append(point(width/2,-7*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO0'))
+      #
+      # pin 26
+      #
+      self.shape = add(self.shape,translate(pad,width/2,-6*pitch,0))
+      self.pad.append(point(width/2,-6*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO4'))
+      #
+      # pin 27
+      #
+      self.shape = add(self.shape,translate(pad,width/2,-5*pitch,0))
+      self.pad.append(point(width/2,-5*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO16'))
+      #
+      # pin 28
+      #
+      self.shape = add(self.shape,translate(pad,width/2,-4*pitch,0))
+      self.pad.append(point(width/2,-4*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO17'))
+      #
+      # pin 29
+      #
+      self.shape = add(self.shape,translate(pad,width/2,-3*pitch,0))
+      self.pad.append(point(width/2,-3*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO5'))
+      #
+      # pin 30
+      #
+      self.shape = add(self.shape,translate(pad,width/2,-2*pitch,0))
+      self.pad.append(point(width/2,-2*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO18'))
+      #
+      # pin 31
+      #
+      self.shape = add(self.shape,translate(pad,width/2,-1*pitch,0))
+      self.pad.append(point(width/2,-1*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO19'))
+      #
+      # pin 32
+      #
+      self.shape = add(self.shape,translate(pad,width/2,0*pitch,0))
+      self.pad.append(point(width/2,0*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'NC'))
+      #
+      # pin 33
+      #
+      self.shape = add(self.shape,translate(pad,width/2,1*pitch,0))
+      self.pad.append(point(width/2,1*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO21'))
+      #
+      # pin 34
+      #
+      self.shape = add(self.shape,translate(pad,width/2,2*pitch,0))
+      self.pad.append(point(width/2,2*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RX0'))
+      #
+      # pin 35
+      #
+      self.shape = add(self.shape,translate(pad,width/2,3*pitch,0))
+      self.pad.append(point(width/2,3*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'TX0'))
+      #
+      # pin 36
+      #
+      self.shape = add(self.shape,translate(pad,width/2,4*pitch,0))
+      self.pad.append(point(width/2,4*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO22'))
+      #
+      # pin 37
+      #
+      self.shape = add(self.shape,translate(pad,width/2,5*pitch,0))
+      self.pad.append(point(width/2,5*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO23'))
+      #
+      # pin 38
+      #
+      self.shape = add(self.shape,translate(pad,width/2,6*pitch,0))
+      self.pad.append(point(width/2,6*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+
+class ESP32_CAM(part):
+   #
+   # ESP32-CAM
+   # Sullins S5635-ND
+   #
+   def __init__(self,value=''):
+      pad_header = cube(-.079/2,.079/2,-.039/2,.039/2,0,0)
+      d = .209/2-.079/2
+      w = 0.9
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_header,+d-w/2,.35,0)
+      self.pad.append(point(+d-w/2,.35,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'+5V'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_header,-d-w/2,.25,0))
+      self.pad.append(point(-d-w/2,.25,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_header,+d-w/2,.15,0))
+      self.pad.append(point(+d-w/2,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO12'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_header,-d-w/2,.05,0))
+      self.pad.append(point(-d-w/2,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO13'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad_header,+d-w/2,-.05,0))
+      self.pad.append(point(+d-w/2,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO15'))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad_header,-d-w/2,-.15,0))
+      self.pad.append(point(-d-w/2,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO14'))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad_header,+d-w/2,-.25,0))
+      self.pad.append(point(+d-w/2,-.25,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO2'))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(pad_header,-d-w/2,-.35,0))
+      self.pad.append(point(-d-w/2,-.35,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO4'))
+      #
+      # pin 9
+      #
+      self.shape = add(self.shape,translate(pad_header,-d+w/2,-.35,0))
+      self.pad.append(point(-d+w/2,-.35,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 10
+      #
+      self.shape = add(self.shape,translate(pad_header,+d+w/2,-.25,0))
+      self.pad.append(point(+d+w/2,-.25,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'U0T'))
+      #
+      # pin 11
+      #
+      self.shape = add(self.shape,translate(pad_header,-d+w/2,-.15,0))
+      self.pad.append(point(-d+w/2,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'U0R'))
+      #
+      # pin 12
+      #
+      self.shape = add(self.shape,translate(pad_header,+d+w/2,-.05,0))
+      self.pad.append(point(+d+w/2,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC'))
+      #
+      # pin 13
+      #
+      self.shape = add(self.shape,translate(pad_header,-d+w/2,.05,0))
+      self.pad.append(point(-d+w/2,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 14
+      #
+      self.shape = add(self.shape,translate(pad_header,+d+w/2,.15,0))
+      self.pad.append(point(+d+w/2,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO0'))
+      #
+      # pin 15
+      #
+      self.shape = add(self.shape,translate(pad_header,-d+w/2,.25,0))
+      self.pad.append(point(-d+w/2,.25,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO16'))
+      #
+      # pin 16
+      #
+      self.shape = add(self.shape,translate(pad_header,+d+w/2,.35,0))
+      self.pad.append(point(+d+w/2,.35,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'3V3'))
+
+
+class ESP8266_12E(part):
+   #
+   # ESP8266 12E
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      height = 24/25.4
+      width = 16/25.4
+      pitch = 2/25.4
+      bottom = 1.8/25.4
+      left = 3/25.4
+      offset = .4/25.4 - .01
+      size = .004
+      pad_ESP8266 = cube(-.0493,.0493,-.0197,.0197,0,0)
+      pad_ESP8266_bot = cube(-.0197,.0197,-.0415,.0415,0,0)
+      #
+      # pin 1:
+      #
+      self.shape = translate(pad_ESP8266,-width/2.0+offset,-height/2.0+bottom+7*pitch,0)
+      self.pad.append(point(-width/2.0+offset,-height/2.0+bottom+7*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RST',line=size))
+      #
+      # pin 2:
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266,-width/2.0+offset,-height/2.0+bottom+6*pitch,0))
+      self.pad.append(point(-width/2.0+offset,-height/2.0+bottom+6*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'ADC',line=size))
+      #
+      # pin 3:
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266,-width/2.0+offset,-height/2.0+bottom+5*pitch,0))
+      self.pad.append(point(-width/2.0+offset,-height/2.0+bottom+5*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'EN',line=size))
+      #
+      # pin 4:
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266,-width/2.0+offset,-height/2.0+bottom+4*pitch,0))
+      self.pad.append(point(-width/2.0+offset,-height/2.0+bottom+4*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GPIO16',line=size))
+      #
+      # pin 5:
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266,-width/2.0+offset,-height/2.0+bottom+3*pitch,0))
+      self.pad.append(point(-width/2.0+offset,-height/2.0+bottom+3*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GPIO14',line=size))
+      #
+      # pin 6:
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266,-width/2.0+offset,-height/2.0+bottom+2*pitch,0))
+      self.pad.append(point(-width/2.0+offset,-height/2.0+bottom+2*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GPIO12',line=size))
+      #
+      # pin 7:
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266,-width/2.0+offset,-height/2.0+bottom+1*pitch,0))
+      self.pad.append(point(-width/2.0+offset,-height/2.0+bottom+1*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GPIO13',line=size))
+      #
+      # pin 8:
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266,-width/2.0+offset,-height/2.0+bottom+0*pitch,0))
+      self.pad.append(point(-width/2.0+offset,-height/2.0+bottom+0*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VDD',line=size))
+      #
+      # pin 9:
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266_bot,-width/2.0+left+0*pitch,-height/2.0+offset,0))
+      self.pad.append(point(-width/2.0+left+0*pitch,-height/2.0+offset,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CS',line=size,angle=90))
+      #
+      # pin 10:
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266_bot,-width/2.0+left+1*pitch,-height/2.0+offset,0))
+      self.pad.append(point(-width/2.0+left+1*pitch,-height/2.0+offset,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'MISO',line=size,angle=90))
+      #
+      # pin 11:
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266_bot,-width/2.0+left+2*pitch,-height/2.0+offset,0))
+      self.pad.append(point(-width/2.0+left+2*pitch,-height/2.0+offset,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GPIO9',line=size,angle=90))
+      #
+      # pin 12:
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266_bot,-width/2.0+left+3*pitch,-height/2.0+offset,0))
+      self.pad.append(point(-width/2.0+left+3*pitch,-height/2.0+offset,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GPIO10',line=size,angle=90))
+      #
+      # pin 13:
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266_bot,-width/2.0+left+4*pitch,-height/2.0+offset,0))
+      self.pad.append(point(-width/2.0+left+4*pitch,-height/2.0+offset,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'MOSI',line=size,angle=90))
+      #
+      # pin 14:
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266_bot,-width/2.0+left+5*pitch,-height/2.0+offset,0))
+      self.pad.append(point(-width/2.0+left+5*pitch,-height/2.0+offset,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCLK',line=size,angle=90))
+      #
+      # pin 15:
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266,width/2.0-offset,-height/2.0+bottom+0*pitch,0))
+      self.pad.append(point(width/2.0-offset,-height/2.0+bottom+0*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=size))
+      #
+      # pin 16:
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266,width/2.0-offset,-height/2.0+bottom+1*pitch,0))
+      self.pad.append(point(width/2.0-offset,-height/2.0+bottom+1*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GPIO15',line=size))
+      #
+      # pin 17:
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266,width/2.0-offset,-height/2.0+bottom+2*pitch,0))
+      self.pad.append(point(width/2.0-offset,-height/2.0+bottom+2*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GPIO2',line=size))
+      #
+      # pin 18:
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266,width/2.0-offset,-height/2.0+bottom+3*pitch,0))
+      self.pad.append(point(width/2.0-offset,-height/2.0+bottom+3*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GPIO0',line=size))
+      #
+      # pin 19:
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266,width/2.0-offset,-height/2.0+bottom+4*pitch,0))
+      self.pad.append(point(width/2.0-offset,-height/2.0+bottom+4*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GPIO4',line=size))
+      #
+      # pin 20:
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266,width/2.0-offset,-height/2.0+bottom+5*pitch,0))
+      self.pad.append(point(width/2.0-offset,-height/2.0+bottom+5*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GPIO5',line=size))
+      #
+      # pin 21:
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266,width/2.0-offset,-height/2.0+bottom+6*pitch,0))
+      self.pad.append(point(width/2.0-offset,-height/2.0+bottom+6*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RXD',line=size))
+      #
+      # pin 22:
+      #
+      self.shape = add(self.shape,translate(pad_ESP8266,width/2.0-offset,-height/2.0+bottom+7*pitch,0))
+      self.pad.append(point(width/2.0-offset,-height/2.0+bottom+7*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'TXD',line=size))
+
+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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_MTA,.025,.1,0))
+      self.pad.append(point(.025,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'2'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1\nGND'))
+      #
+      # pin 2: Vcc
+      #
+      self.shape = add(self.shape,translate(pad_MTA,.025,.1,0))
+      self.pad.append(point(.025,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Vcc'))
+      #
+      # 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_3(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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1'))
+      #
+      # pin 2: power
+      #
+      self.shape = add(self.shape,translate(pad_MTA,-.05,.1,0))
+      self.pad.append(point(-.05,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'2'))
+      #
+      # pin 3: data
+      #
+      self.shape = add(self.shape,translate(pad_MTA,0,-.1,0))
+      self.pad.append(point(0,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'3'))
+      #
+      # 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_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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1\nGND'))
+      #
+      # pin 2: power
+      #
+      self.shape = add(self.shape,translate(pad_MTA,-.05,.1,0))
+      self.pad.append(point(-.05,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V'))
+      #
+      # pin 3: data
+      #
+      self.shape = add(self.shape,translate(pad_MTA,0,-.1,0))
+      self.pad.append(point(0,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'data'))
+      #
+      # 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_4(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
+      #
+      self.shape = translate(pad_MTA,-.075,-.1,0)
+      self.pad.append(point(-.075,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_MTA,.025,-.1,0))
+      self.pad.append(point(.025,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'2'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_MTA,.075,.1,0))
+      self.pad.append(point(.075,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'3'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_MTA,-.025,.1,0))
+      self.pad.append(point(-.025,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'4'))
+      #
+      # 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_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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1'))
+      #
+      # pin 2: Tx
+      #
+      self.shape = add(self.shape,translate(pad_MTA,.025,-.1,0))
+      self.pad.append(point(.025,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Tx'))
+      #
+      # pin 3: Rx
+      #
+      self.shape = add(self.shape,translate(pad_MTA,.075,.1,0))
+      self.pad.append(point(.075,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Rx'))
+      #
+      # pin 4: DTR
+      #
+      self.shape = add(self.shape,translate(pad_MTA,-.025,.1,0))
+      self.pad.append(point(-.025,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DTR'))
+      #
+      # 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_PS2(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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1\nGND'))
+      #
+      # pin 2: data
+      #
+      self.shape = add(self.shape,translate(pad_MTA,.025,-.1,0))
+      self.pad.append(point(.025,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'data'))
+      #
+      # pin 3: clock
+      #
+      self.shape = add(self.shape,translate(pad_MTA,.075,.1,0))
+      self.pad.append(point(.075,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'clock'))
+      #
+      # pin 4: 5V
+      #
+      self.shape = add(self.shape,translate(pad_MTA,-.025,.1,0))
+      self.pad.append(point(-.025,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'5V'))
+      #
+      # 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_5(part):
+   #
+   # AMP 1445121-5
+   # MTA .050 SMT 5-pin vertical
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_MTA,-.1,-.1,0)
+      self.pad.append(point(-.1,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_MTA,0,-.1,0))
+      self.pad.append(point(0,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'2'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_MTA,.1,-.1,0))
+      self.pad.append(point(.1,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'3'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_MTA,.05,.1,0))
+      self.pad.append(point(.05,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'4'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad_MTA,-.05,.1,0))
+      self.pad.append(point(-.05,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'5'))
+      #
+      # 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 MTA_ICP(part):
+   #
+   # AMP 1445121-5
+   # MTA .050 SMT 5-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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'MISO'))
+      #
+      # pin 2: GND
+      #
+      self.shape = add(self.shape,translate(pad_MTA,0,-.1,0))
+      self.pad.append(point(0,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 3: MOSI
+      #
+      self.shape = add(self.shape,translate(pad_MTA,.1,-.1,0))
+      self.pad.append(point(.1,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'MOSI'))
+      #
+      # pin 4: -RESET
+      #
+      self.shape = add(self.shape,translate(pad_MTA,.05,.1,0))
+      self.pad.append(point(.05,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'-RESET'))
+      #
+      # pin 5: SCK
+      #
+      self.shape = add(self.shape,translate(pad_MTA,-.05,.1,0))
+      self.pad.append(point(-.05,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCK'))
+      #
+      # 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))
+
+pad_screw_terminal = cylinder(0,0,0,0,.047)
+hole_screw_terminal = circle(0,0,.025)
+
+class screw_terminal_2(part):
+   #
+   # On Shore ED555/2DS
+   # two position screw terminal
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_screw_terminal,-.069,0,0)
+      self.pad.append(point(-.069,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_screw_terminal,.069,0,0))
+      self.pad.append(point(.069,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'2'))
+      #
+      # holes
+      #
+      self.shape = add(self.shape,translate(hole_screw_terminal,-.069,0,0))
+      self.shape = add(self.shape,translate(hole_screw_terminal,.069,0,0))
+
+class screw_terminal_power(part):
+   #
+   # On Shore ED555/2DS
+   # power screw terminal
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_screw_terminal,-.069,0,0)
+      self.pad.append(point(-.069,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_screw_terminal,.069,0,0))
+      self.pad.append(point(.069,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V'))
+      #
+      # holes
+      #
+      self.shape = add(self.shape,translate(hole_screw_terminal,-.069,0,0))
+      self.shape = add(self.shape,translate(hole_screw_terminal,.069,0,0))
+
+class screw_terminal_i0(part):
+   #
+   # On Shore ED555/3DS
+   # i0 screw terminal
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: Gnd
+      #
+      self.shape = translate(pad_screw_terminal,-.138,0,0)
+      self.pad.append(point(-.138,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Gnd\n1'))
+      #
+      # pin 2: data
+      #
+      self.shape = add(self.shape,pad_screw_terminal)
+      self.pad.append(point(0,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'data'))
+      #
+      # pin 3: V
+      #
+      self.shape = add(self.shape,translate(pad_screw_terminal,.138,0,0))
+      self.pad.append(point(.138,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V'))
+      #
+      # holes
+      #
+      self.shape = add(self.shape,translate(hole_screw_terminal,-.138,0,0))
+      self.shape = add(self.shape,hole_screw_terminal)
+      self.shape = add(self.shape,translate(hole_screw_terminal,.138,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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'P'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'C'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'base'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'tip'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'middle'))
+
+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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Rx'))
+      #
+      # pin 2: Tx
+      #
+      self.shape = add(self.shape,translate(pad_Molex,-.025,.064,0))
+      self.pad.append(point(-.025,.064,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Tx'))
+      #
+      # pin 3: DTR
+      #
+      self.shape = add(self.shape,translate(pad_Molex,.025,.064,0))
+      self.pad.append(point(.025,.064,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DTR'))
+      #
+      # pin 4: GND
+      #
+      self.shape = add(self.shape,translate(pad_Molex,.075,.064,0))
+      self.pad.append(point(.075,.064,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # 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
+############################################################
+
+class slide_switch(part):
+   #
+   # slide switch
+   # C&K AYZ0102AGRLC
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      pad = cube(-.039/2,.039/2,-.047/2,.047/2,0,0)
+      #
+      # pad 1
+      #
+      self.shape = translate(pad,-.098,.1,0)
+      self.pad.append(point(-.098,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,''))
+      #
+      # pad 2
+      #
+      self.shape = add(self.shape,translate(pad,0,.1,0))
+      self.pad.append(point(0,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,''))
+      #
+      # pad 3
+      #
+      self.shape = add(self.shape,translate(pad,.098,.1,0))
+      self.pad.append(point(.098,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,''))
+      #
+      # holes
+      #
+      self.holes = cylinder(-.118/2,0,zb,zt,.034/2)
+      self.holes = add(self.holes,cylinder(.118/2,0,zb,zt,.034/2))
+
+class button_6mm(part):
+   #
+   # Omron 6mm pushbutton
+   # B3SN-3112P
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      pad_button_6mm = cube(-.04,.04,-.03,.03,0,0)
+      #
+      # left 1
+      #
+      self.shape = translate(pad_button_6mm,-.125,.08,0)
+      self.pad.append(point(-.125,.08,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'L1'))
+      #
+      # right 1
+      #
+      self.shape = add(self.shape,translate(pad_button_6mm,-.125,-.08,0))
+      self.pad.append(point(-.125,-.08,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'R1'))
+      #
+      # right 2
+      #
+      self.shape = add(self.shape,translate(pad_button_6mm,.125,-.08,0))
+      self.pad.append(point(.125,-.08,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'R2'))
+      #
+      # left 2
+      #
+      self.shape = add(self.shape,translate(pad_button_6mm,.125,.08,0))
+      self.pad.append(point(.125,.08,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'L2'))
+
+############################################################
+# crystals and resonators
+############################################################
+
+pad_XTAL_EFOBM = cube(-.016,.016,-.085,.085,0,0)
+
+class XTAL_EFOBM(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_EFOBM,-.053,0,0)
+      self.pad.append(point(-.053,0,0))
+      #
+      # ground
+      #
+      self.shape = add(self.shape,translate(pad_XTAL_EFOBM,0,0,0))
+      self.pad.append(point(0,0,0))
+      #
+      # right
+      #
+      self.shape = add(self.shape,translate(pad_XTAL_EFOBM,.053,0,0))
+      self.pad.append(point(.053,0,0))
+
+pad_XTAL_NX5032GA = cube(-.039,.039,-.047,.047,0,0)
+.079
+
+class XTAL_NX5032GA(part):
+   #
+   # NDK NX5032GA
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # left
+      #
+      self.shape = translate(pad_XTAL_NX5032GA,-.079,0,0)
+      self.pad.append(point(-.079,0,0))
+      #
+      # right
+      #
+      self.shape = add(self.shape,translate(pad_XTAL_NX5032GA,.079,0,0))
+      self.pad.append(point(.079,0,0))
+
+pad_XTAL_CSM_7 = cube(-.108,.108,-.039,.039,0,0)
+
+class XTAL_CSM_7(part):
+   #
+   # ECS CSM-7 series
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # left
+      #
+      self.shape = translate(pad_XTAL_CSM_7,-.187,0,0)
+      self.pad.append(point(-.187,0,0))
+      #
+      # right
+      #
+      self.shape = add(self.shape,translate(pad_XTAL_CSM_7,.187,0,0))
+      self.pad.append(point(.187,0,0))
+
+############################################################
+# diodes, transistors, regulators, sensors
+############################################################
+
+class DRV8428P_HTSSOP(part):
+   #
+   # TI DRV8428PPWPR stepper driver
+   #    HTSSOP package
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      d = 0.12
+      w = 0.029
+      h = 0.0053
+      p = 0.02559
+      pad = cube(-w,w,-h,h,0,0)
+      s = 0.003
+      #
+      # pin 1
+      #
+      self.shape = translate(pad,-d,3.5*p,0)
+      self.shape = add(self.shape,cylinder(-d-w,3.5*p,0,0,h))
+      self.pad.append(point(-d,3.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'.VM',line=s))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad,-d,2.5*p,0))
+      self.pad.append(point(-d,2.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PGND',line=s))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad,-d,1.5*p,0))
+      self.pad.append(point(-d,1.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'AOUT1',line=s))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad,-d,.5*p,0))
+      self.pad.append(point(-d,.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'AOUT2',line=s))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.5*p,0))
+      self.pad.append(point(-d,-.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'BOUT2',line=s))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad,-d,-1.5*p,0))
+      self.pad.append(point(-d,-1.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'BOUT1',line=s))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad,-d,-2.5*p,0))
+      self.pad.append(point(-d,-2.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=s))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(pad,-d,-3.5*p,0))
+      self.pad.append(point(-d,-3.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DVDD',line=s))
+      #
+      # pin 9
+      #
+      self.shape = add(self.shape,translate(pad,d,-3.5*p,0))
+      self.pad.append(point(d,-3.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VREFB',line=s))
+      #
+      # pin 10
+      #
+      self.shape = add(self.shape,translate(pad,d,-2.5*p,0))
+      self.pad.append(point(d,-2.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VREFA',line=s))
+      #
+      # pin 11
+      #
+      self.shape = add(self.shape,translate(pad,d,-1.5*p,0))
+      self.pad.append(point(d,-1.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DECAY',line=s))
+      #
+      # pin 12
+      #
+      self.shape = add(self.shape,translate(pad,d,-.5*p,0))
+      self.pad.append(point(d,-.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'BIN2',line=s))
+      #
+      # pin 13
+      #
+      self.shape = add(self.shape,translate(pad,d,.5*p,0))
+      self.pad.append(point(d,.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'BIN1',line=s))
+      #
+      # pin 14
+      #
+      self.shape = add(self.shape,translate(pad,d,1.5*p,0))
+      self.pad.append(point(d,1.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'AIN2',line=s))
+      #
+      # pin 15
+      #
+      self.shape = add(self.shape,translate(pad,d,2.5*p,0))
+      self.pad.append(point(d,2.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'AIN1',line=s))
+      #
+      # pin 16
+      #
+      self.shape = add(self.shape,translate(pad,d,3.5*p,0))
+      self.pad.append(point(d,3.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SLEEP',line=s))
+      #
+      # pin 17
+      #
+      self.shape = add(self.shape,translate(cube(-.06,.06,-.09,.09,0,0),0,0,0))
+      self.pad.append(point(0,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=s))
+
+class LED_3014_1100(part):
+   #
+   # Luminus MP-3014-1100-50-80
+   #
+   def __init__(self,value=''):
+      anode = cube(-.011,.011,-.027,.027,0,0)
+      cathode = cube(-.036,.036,-.027,.027,0,0)
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # anode
+      #
+      self.shape = translate(anode,-.047,0,0)
+      self.pad.append(point(-.047,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A'))
+      #
+      # cathode
+      #
+      self.shape = add(self.shape,translate(cathode,.022,0,0))
+      self.pad.append(point(.022,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'C'))
+
+class CMM4030D261I2STR(part):
+   #
+   # CUI CMM-4030D-261-I2S-TR I2S microphone
+   #
+   def __init__(self,value=''):
+      pad = cube(-.018,.018,-.011,.011,0,0)
+      self.value = value
+      self.x = 0
+      self.y = 0
+      self.z = 0
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      s = 0.004
+      #
+      # pin 1
+      #
+      self.shape = translate(pad,.037,-.059,0)
+      self.pad.append(point(.037,-.059,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND.',line=s))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad,.037,-.019,0))
+      self.pad.append(point(.037,-.019,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'N/C',line=s))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad,.037,.019,0))
+      self.pad.append(point(.037,.019,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'WS',line=s))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad,.037,.059,0))
+      self.pad.append(point(.037,.059,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'EN',line=s))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad,-.037,.059,0))
+      self.pad.append(point(-.037,.059,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'L/R',line=s))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad,-.037,.019,0))
+      self.pad.append(point(-.037,.019,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCK',line=s))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad,-.037,-.019,0))
+      self.pad.append(point(-.037,-.019,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SD',line=s))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(pad,-.037,-.059,0))
+      self.pad.append(point(-.037,-.059,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VDD',line=s))
+
+class SPG08P4HM4H(part):
+   #
+   # Knowles SPG08P4HM4H-1 PDM microphone
+   #
+   def __init__(self,value=''):
+      pad = cube(-.011,.011,-.011,.011,0,0)
+      self.value = value
+      self.x = 0
+      self.y = 0
+      self.z = 0
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      s = 0.004
+      #
+      # pin 1
+      #
+      self.shape = translate(pad,.023,-.037,0)
+      self.pad.append(point(.023,-.037,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V.',line=s))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad,.023,0,0))
+      self.pad.append(point(.023,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G',line=s))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad,.023,.037,0))
+      self.pad.append(point(.023,.037,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DAT',line=s))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad,-.023,.037,0))
+      self.pad.append(point(-.023,.037,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CK',line=s))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad,-.023,0,0))
+      self.pad.append(point(-.023,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G',line=s))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad,-.023,-.037,0))
+      self.pad.append(point(-.023,-.037,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SEL',line=s))
+
+class VEML6040(part):
+   #
+   # Vishay VEML6040 color sensor
+   #
+   def __init__(self,value=''):
+      pad12 = cube(-.016,.019,-.006,.006,0,0)
+      pad3 = cube(-.023,.016,-.006,.006,0,0)
+      pad4 = cube(-.019,.016,-.006,.006,0,0)
+      self.value = value
+      self.x = 0
+      self.y = 0
+      self.z = 0
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      s = 0.004
+      #
+      # pin 1
+      #
+      self.shape = translate(pad12,-.039,.014,0)
+      self.pad.append(point(-.039,.014,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1GND',line=s))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad12,-.039,-.014,0))
+      self.pad.append(point(-.039,-.014,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SDA',line=s))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad3,.039,-.014,0))
+      self.pad.append(point(.039,-.014,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCL',line=s))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad4,.039,.014,0))
+      self.pad.append(point(.039,.014,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VDD',line=s))
+
+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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A'))
+      #
+      # cathode
+      #
+      self.shape = add(self.shape,translate(pad_1206,.06,0,0))
+      self.pad.append(point(.055,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'C'))
+
+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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A'))
+      #
+      # cathode
+      #
+      self.shape = add(self.shape,translate(pad_1206,.06,0,0))
+      self.pad.append(point(.055,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'C'))
+
+pad_RGB = cube(-.02,.02,-.029,.029,0,0)
+
+class LED_RGB(part):
+   #
+   # CREE CLV1A-FKB
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.x = 0
+      self.y = 0
+      self.z = 0
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      dx = .029
+      dy = .059
+      #
+      # pin 1: red
+      #
+      self.shape = translate(pad_RGB,-dx,-dy,0)
+      self.shape = add(self.shape,cylinder(-dx,-dy-.029,0,0,.02))
+      self.pad.append(point(-dx,-dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'R'))
+      #
+      # pin 2: anode
+      #
+      self.shape = add(self.shape,translate(pad_RGB,dx,-dy,0))
+      self.pad.append(point(dx,-dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A'))
+      #
+      # pin 3: blue
+      #
+      self.shape = add(self.shape,translate(pad_RGB,dx,dy,0))
+      self.pad.append(point(dx,dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'B'))
+      #
+      # pin 4: green
+      #
+      self.shape = add(self.shape,translate(pad_RGB,-dx,dy,0))
+      self.pad.append(point(-dx,dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G'))
+
+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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'C'))
+      #
+      # emitter
+      #
+      self.shape = add(self.shape,translate(pad_1206,.06,0,0))
+      self.pad.append(point(.055,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'E'))
+
+pad_PLCC2 = cube(-.029,.029,-.059,.059,0,0)
+
+class phototransistor_PLCC2(part):
+   #
+   # PLCC2 phototransistor
+   # Optek OP580
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # collector
+      #
+      self.shape = translate(pad_PLCC2,-.065,0,0)
+      self.pad.append(point(-.065,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'C'))
+      #
+      # emitter
+      #
+      self.shape = add(self.shape,translate(pad_PLCC2,.065,0,0))
+      self.pad.append(point(.065,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'E'))
+
+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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A'))
+      #
+      # cathode
+      #
+      self.shape = add(self.shape,translate(pad_SOD_123,.07,0,0))
+      self.pad.append(point(.07,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'C'))
+
+pad_SOT23 = cube(-.02,.02,-.012,.012,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,.045,-.0375,0)
+      self.pad.append(point(.045,-.0375,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G'))
+      #
+      # pin 2: source
+      #
+      self.shape = add(self.shape,translate(pad_SOT23,.045,.0375,0))
+      self.pad.append(point(.045,.0375,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'S'))
+      #
+      # pin 3: drain
+      #
+      self.shape = add(self.shape,translate(pad_SOT23,-.045,0,0))
+      self.pad.append(point(-.045,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'D'))
+
+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,.045,-.0375,0)
+      self.pad.append(point(.045,-.0375,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G'))
+      #
+      # pin 2: source
+      #
+      self.shape = add(self.shape,translate(pad_SOT23,.045,.0375,0))
+      self.pad.append(point(.045,.0375,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'S'))
+      #
+      # pin 3: drain
+      #
+      self.shape = add(self.shape,translate(pad_SOT23,-.045,0,0))
+      self.pad.append(point(-.045,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'D'))
+
+class NMOSFET_TO252AA(part):
+   #
+   # Fairchild RFD16N05LSM
+   #
+   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(cube(-.031,.031,-.059,.059,0,0),-.090,0,0)
+      self.pad.append(point(-.090,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G 1'))
+      #
+      # pin 2: source
+      #
+      self.shape = add(self.shape,translate(cube(-.031,.031,-.059,.059,0,0),.090,0,0))
+      self.pad.append(point(.090,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'S'))
+      #
+      # pin 3: drain
+      #
+      self.shape = add(self.shape,translate(cube(-.132,.132,-.132,.132,0,0),0,.261,0))
+      self.pad.append(point(0,.261,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'D'))
+
+class Hall_SOT23(part):
+   #
+   # Allegro A1324
+   #
+   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,-.045,.0375,0)
+      self.pad.append(point(-.045,.0375,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Vcc'))
+      #
+      # pin 2: input
+      #
+      self.shape = add(self.shape,translate(pad_SOT23,-.045,-.0375,0))
+      self.pad.append(point(-.045,-.0375,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'out'))
+      #
+      # pin 3: ground
+      #
+      self.shape = add(self.shape,translate(pad_SOT23,.045,0,0))
+      self.pad.append(point(.045,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'gnd'))
+
+class regulator_SOT23(part):
+   #
+   # TI LM3480IM3
+   #
+   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,-.045,.0375,0)
+      self.pad.append(point(-.045,.0375,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'out'))
+      #
+      # pin 2: input
+      #
+      self.shape = add(self.shape,translate(pad_SOT23,-.045,-.0375,0))
+      self.pad.append(point(-.045,-.0375,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'in'))
+      #
+      # pin 3: ground
+      #
+      self.shape = add(self.shape,translate(pad_SOT23,.045,0,0))
+      self.pad.append(point(.045,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'gnd'))
+
+class regulator_SOT223(part):
+   #
+   # Zetex ZLDO1117
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.x = 0
+      self.y = 0
+      self.z = 0
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      pad_SOT223 = cube(-.02,.02,-.03,.03,0,0)
+      pad_SOT223_ground = cube(-.065,.065,-.03,.03,0,0)
+      #
+      # pin 1: GND
+      #
+      self.shape = translate(pad_SOT223,-.09,-.12,0)
+      self.pad.append(point(-.09,-.12,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1G'))
+      #
+      # pin 2: output
+      #
+      self.shape = add(self.shape,translate(pad_SOT223,0,-.12,0))
+      self.pad.append(point(0,-.12,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'O'))
+      #
+      # pin 3: input
+      #
+      self.shape = add(self.shape,translate(pad_SOT223,.09,-.12,0))
+      self.pad.append(point(.09,-.12,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'I'))
+      #
+      # pin 4: output
+      #
+      self.shape = add(self.shape,translate(pad_SOT223_ground,0,.12,0))
+      self.pad.append(point(0,.12,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'out'))
+
+class A4953_SOICN(part):
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: GND
+      #
+      self.shape = translate(pad_SOIC,-.11,.075,0)
+      self.shape = add(self.shape,cylinder(-.153,.075,0,0,.015))
+      self.pad.append(point(-.11,.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 2: IN2
+      #
+      self.shape = add(self.shape,translate(pad_SOIC,-.11,.025,0))
+      self.pad.append(point(-.11,.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IN2'))
+      #
+      # pin 3: IN1
+      #
+      self.shape = add(self.shape,translate(pad_SOIC,-.11,-.025,0))
+      self.pad.append(point(-.11,-.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IN1'))
+      #
+      # pin 4: VREF
+      #
+      self.shape = add(self.shape,translate(pad_SOIC,-.11,-.075,0))
+      self.pad.append(point(-.11,-.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VREF'))
+      #
+      # pin 5: VBB
+      #
+      self.shape = add(self.shape,translate(pad_SOIC,.11,-.075,0))
+      self.pad.append(point(.11,-.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VBB'))
+      #
+      # pin 6: OUT1
+      #
+      self.shape = add(self.shape,translate(pad_SOIC,.11,-.025,0))
+      self.pad.append(point(.11,-.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'OUT1'))
+      #
+      # pin 7: LSS
+      #
+      self.shape = add(self.shape,translate(pad_SOIC,.11,.025,0))
+      self.pad.append(point(.11,.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'LSS'))
+      #
+      # pin 8: OUT2
+      #
+      self.shape = add(self.shape,translate(pad_SOIC,.11,.075,0))
+      self.pad.append(point(.11,.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'OUT2'))
+      #
+      # thermal pad
+      #
+      self.shape = add(self.shape,rectangle(-.04,.04,-.075,.075))
+
+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.shape = add(self.shape,cylinder(-d-.035,.09,0,0,.016))
+      self.pad.append(point(-d,.09,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GRN'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SN'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GLN'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GLP'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DL'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SP'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DR'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GRP'))
+
+pad_mic = cylinder(0,0,0,0,.02)
+
+class mic_SPU0414HR5H(part):
+   #
+   # Knowles SPU0414HR5H-SB
+   #
+   def __init__(self,value=''):
+      s = 0.004
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: Vdd
+      #
+      self.shape = translate(pad_mic,.033,.048,0)
+      self.pad.append(point(.033,.048,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V1',line=s))
+      #
+      # pin 2: GND
+      #
+      self.shape = add(self.shape,translate(pad_mic,.033,-.048,0))
+      self.pad.append(point(.033,-.048,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=s))
+      #
+      # pin 3: gain
+      #
+      self.shape = add(self.shape,translate(pad_mic,-.033,-.048,0))
+      self.pad.append(point(-.033,-.048,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'gain',line=s))
+      #
+      # pin 4: out
+      #
+      self.shape = add(self.shape,translate(pad_mic,-.033,.048,0))
+      self.pad.append(point(-.033,.048,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'out',line=s))
+
+class mic_SPM1437(part):
+   #
+   # Knowles SPM1437HM4H-B
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_mic,-.046,.065,0)
+      #self.shape = add(self.shape,cylinder(-.183,.075,0,0,.015))
+      self.pad.append(point(-.046,.065,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_mic,-.046,0,0))
+      self.pad.append(point(-.046,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SEL'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_mic,-.046,-.065,0))
+      self.pad.append(point(-.046,-.065,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_mic,.046,-.065,0))
+      self.pad.append(point(.046,-.065,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CLK'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad_mic,.046,0,0))
+      self.pad.append(point(.046,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DAT'))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad_mic,.046,.065,0))
+      self.shape = add(self.shape,translate(pad_mic,.038,.057,0))
+      self.pad.append(point(.046,.065,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V'))
+
+pad_accel = cube(-.03,.03,-.0125,.0125,0,0)
+pad_accel90 = cube(-.0125,.0125,-.03,.03,0,0)
+
+class accel_MXD6235M(part):
+   #
+   # MEMSIC MXD6235M
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_accel,-.1,.05,0)
+      self.shape = add(self.shape,cylinder(-.13,.05,0,0,.0125))
+      self.pad.append(point(-.1,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_accel,-.1,0,0))
+      self.pad.append(point(-.1,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'TP'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_accel,-.1,-.05,0))
+      self.pad.append(point(-.1,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_accel90,0,-.1,0))
+      self.pad.append(point(0,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'NC'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad_accel,.1,-.05,0))
+      self.pad.append(point(.1,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'NC'))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad_accel,.1,0,0))
+      self.pad.append(point(.1,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Y'))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad_accel,.1,.05,0))
+      self.pad.append(point(.1,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'X'))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(pad_accel90,0,.1,0))
+      self.pad.append(point(0,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V'))
+      #
+      # ground plane
+      #
+      self.shape = add(self.shape,cube(-.05,.05,-.05,.05,0,0))
+
+pad_cc_14_1 = cube(-.014,.014,-.0075,.0075,0,0)
+pad_cc_14_1_90 = cube(-.0075,.0075,-.014,.014,0,0)
+
+class ADXL343(part):
+   #
+   # ADI ADXL343 accelerometer
+   #
+   def __init__(self,value=''):
+      d = 0.8/25.4
+      w = 1.01/25.4
+      s = 0.004
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad_cc_14_1,-w,2.5*d,0)
+      self.pad.append(point(-w,2.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,"VD1",line=s))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad_cc_14_1,-w,1.5*d,0))
+      self.pad.append(point(-w,1.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=s))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad_cc_14_1,-w,.5*d,0))
+      self.pad.append(point(-w,.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RSV',line=s))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad_cc_14_1,-w,-.5*d,0))
+      self.pad.append(point(-w,-.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=s))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad_cc_14_1,-w,-1.5*d,0))
+      self.pad.append(point(-w,-1.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=s))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad_cc_14_1,-w,-2.5*d,0))
+      self.pad.append(point(-w,-2.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VS',line=s))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad_cc_14_1_90,0,-2.5*d,0))
+      self.pad.append(point(0,-2.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'-CS',angle=90,line=s))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(pad_cc_14_1,w,-2.5*d,0))
+      self.pad.append(point(w,-2.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'INT1',line=s))
+      #
+      # pin 9
+      #
+      self.shape = add(self.shape,translate(pad_cc_14_1,w,-1.5*d,0))
+      self.pad.append(point(w,-1.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'INT2',line=s))
+      #
+      # pin 10
+      #
+      self.shape = add(self.shape,translate(pad_cc_14_1,w,-.5*d,0))
+      self.pad.append(point(w,-.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'NC',line=s))
+      #
+      # pin 11
+      #
+      self.shape = add(self.shape,translate(pad_cc_14_1,w,.5*d,0))
+      self.pad.append(point(w,.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RSV',line=s))
+      #
+      # pin 12
+      #
+      self.shape = add(self.shape,translate(pad_cc_14_1,w,1.5*d,0))
+      self.pad.append(point(w,1.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'ALT',line=s))
+      #
+      # pin 13
+      #
+      self.shape = add(self.shape,translate(pad_cc_14_1,w,2.5*d,0))
+      self.pad.append(point(w,2.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SDA',line=s))
+      #
+      # pin 14
+      #
+      self.shape = add(self.shape,translate(pad_cc_14_1_90,0,2.5*d,0))
+      self.pad.append(point(0,2.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCL',angle=90,line=s))
+
+class VL53L1X(part):
+   #
+   # ST VL53L1X time of flight sensor
+   #
+   def __init__(self,value=''):
+      pad = cube(-.0075,.0075,-.0075,.0075,0,0)
+      d = 0.8/25.4
+      w = 0.8/25.4
+      s = 0.004
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      self.shape = translate(pad,-w,-2*d,0)
+      self.pad.append(point(-w,-2*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,"1V",line=s))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad,-w,-1*d,0))
+      self.pad.append(point(-w,-1*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G',line=s))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad,-w,0*d,0))
+      self.pad.append(point(-w,0*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G',line=s))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad,-w,1*d,0))
+      self.pad.append(point(-w,1*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G',line=s))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad,-w,2*d,0))
+      self.pad.append(point(-w,2*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'XS',line=s))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad,0,2*d,0))
+      self.pad.append(point(0,2*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G',line=s))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad,w,2*d,0))
+      self.pad.append(point(w,2*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IO',line=s))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(pad,w,1*d,0))
+      self.pad.append(point(w,1*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'NC',line=s))
+      #
+      # pin 9
+      #
+      self.shape = add(self.shape,translate(pad,w,0*d,0))
+      self.pad.append(point(w,0*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SDA',line=s))
+      #
+      # pin 10
+      #
+      self.shape = add(self.shape,translate(pad,w,-1*d,0))
+      self.pad.append(point(w,-1*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCL',line=s))
+      #
+      # pin 11
+      #
+      self.shape = add(self.shape,translate(pad,w,-2*d,0))
+      self.pad.append(point(w,-2*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V',line=s))
+      #
+      # pin 12
+      #
+      self.shape = add(self.shape,translate(pad,0,-2*d,0))
+      self.pad.append(point(0,-2*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'G',line=s))
+
+############################################################
+# ICs
+############################################################
+
+class AVRDB28(part):
+   #
+   # AVR*DB28
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      d = 9.01/2/25.4 # spacing
+      w = 0.4/2/25.4 # width
+      h = 1.4/2/25.4 # height
+      p = 0.8/25.4 # pitch
+      l = 0.004 # text
+      pad = cube(-h,h,-w,w,0,0)
+      padv = cube(-w,w,-h,h,0,0)
+      #
+      # pin 1
+      #
+      self.shape = translate(pad,-d,3.5*p,0)
+      self.shape = add(self.shape,cylinder(-d-h,3.5*p,0,0,w))
+      self.pad.append(point(-d,3.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'.PA3',line=l))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad,-d,2.5*p,0))
+      self.pad.append(point(-d,2.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA4',line=l))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad,-d,1.5*p,0))
+      self.pad.append(point(-d,1.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA5',line=l))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad,-d,.5*p,0))
+      self.pad.append(point(-d,.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA6',line=l))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.5*p,0))
+      self.pad.append(point(-d,-.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA7',line=l))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad,-d,-1.5*p,0))
+      self.pad.append(point(-d,-1.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC0',line=l))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad,-d,-2.5*p,0))
+      self.pad.append(point(-d,-2.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC1',line=l))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(pad,-d,-3.5*p,0))
+      self.pad.append(point(-d,-3.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC2',line=l))
+      #
+      # pin 9
+      #
+      self.shape = add(self.shape,translate(padv,-3.5*p,-d,0))
+      self.pad.append(point(-3.5*p,-d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC3',line=l,angle=-90))
+      #
+      # pin 10
+      #
+      self.shape = add(self.shape,translate(padv,-2.5*p,-d,0))
+      self.pad.append(point(-2.5*p,-d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VIO2',line=l,angle=-90))
+      #
+      # pin 11
+      #
+      self.shape = add(self.shape,translate(padv,-1.5*p,-d,0))
+      self.pad.append(point(-1.5*p,-d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD1',line=l,angle=-90))
+      #
+      # pin 12
+      #
+      self.shape = add(self.shape,translate(padv,-.5*p,-d,0))
+      self.pad.append(point(-.5*p,-d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD2',line=l,angle=-90))
+      #
+      # pin 13
+      #
+      self.shape = add(self.shape,translate(padv,.5*p,-d,0))
+      self.pad.append(point(.5*p,-d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD3',line=l,angle=-90))
+      #
+      # pin 14
+      #
+      self.shape = add(self.shape,translate(padv,1.5*p,-d,0))
+      self.pad.append(point(1.5*p,-d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD4',line=l,angle=-90))
+      #
+      # pin 15
+      #
+      self.shape = add(self.shape,translate(padv,2.5*p,-d,0))
+      self.pad.append(point(2.5*p,-d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD5',line=l,angle=-90))
+      #
+      # pin 16
+      #
+      self.shape = add(self.shape,translate(padv,3.5*p,-d,0))
+      self.pad.append(point(3.5*p,-d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD6',line=l,angle=-90))
+      #
+      # pin 17
+      #
+      self.shape = add(self.shape,translate(pad,d,-3.5*p,0))
+      self.pad.append(point(d,-3.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD7',line=l))
+      #
+      # pin 18
+      #
+      self.shape = add(self.shape,translate(pad,d,-2.5*p,0))
+      self.pad.append(point(d,-2.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'AVDD',line=l))
+      #
+      # pin 19
+      #
+      self.shape = add(self.shape,translate(pad,d,-1.5*p,0))
+      self.pad.append(point(d,-1.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=l))
+      #
+      # pin 20
+      #
+      self.shape = add(self.shape,translate(pad,d,-.5*p,0))
+      self.pad.append(point(d,-.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PF0',line=l))
+      #
+      # pin 21
+      #
+      self.shape = add(self.shape,translate(pad,d,.5*p,0))
+      self.pad.append(point(d,.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PF1',line=l))
+      #
+      # pin 22
+      #
+      self.shape = add(self.shape,translate(pad,d,1.5*p,0))
+      self.pad.append(point(d,1.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PF2',line=l))
+      #
+      # pin 23
+      #
+      self.shape = add(self.shape,translate(pad,d,2.5*p,0))
+      self.pad.append(point(d,2.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PF3',line=l))
+      #
+      # pin 24
+      #
+      self.shape = add(self.shape,translate(pad,d,3.5*p,0))
+      self.pad.append(point(d,3.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PF4',line=l))
+      #
+      # pin 25
+      #
+      self.shape = add(self.shape,translate(padv,3.5*p,d,0))
+      self.pad.append(point(3.5*p,d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PF5',line=l,angle=-90))
+      #
+      # pin 26
+      #
+      self.shape = add(self.shape,translate(padv,2.5*p,d,0))
+      self.pad.append(point(2.5*p,d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PF6',line=l,angle=-90))
+      #
+      # pin 27
+      #
+      self.shape = add(self.shape,translate(padv,1.5*p,d,0))
+      self.pad.append(point(1.5*p,d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'UPDI',line=l,angle=-90))
+      #
+      # pin 28
+      #
+      self.shape = add(self.shape,translate(padv,.5*p,d,0))
+      self.pad.append(point(.5*p,d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VDD',line=l,angle=-90))
+      #
+      # pin 29
+      #
+      self.shape = add(self.shape,translate(padv,-.5*p,d,0))
+      self.pad.append(point(-.5*p,d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=l,angle=-90))
+      #
+      # pin 30
+      #
+      self.shape = add(self.shape,translate(padv,-1.5*p,d,0))
+      self.pad.append(point(-1.5*p,d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA0',line=l,angle=-90))
+      #
+      # pin 31
+      #
+      self.shape = add(self.shape,translate(padv,-2.5*p,d,0))
+      self.pad.append(point(-2.5*p,d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA1',line=l,angle=-90))
+      #
+      # pin 32
+      #
+      self.shape = add(self.shape,translate(padv,-3.5*p,d,0))
+      self.pad.append(point(-3.5*p,d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA2',line=l,angle=-90))
+
+class ATtiny3216(part):
+   #
+   # SOIC-20
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      d = 9.82/2/25.4
+      w = .63/2/25.4
+      h = 1.9/2/25.4
+      pad = cube(-h,h,-w,w,0,0)
+      #
+      # pin 1
+      #
+      self.shape = translate(pad,-d,.225,0)
+      self.shape = add(self.shape,cylinder(-d-h,.225,0,0,w))
+      self.pad.append(point(-d,.225,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1VCC'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad,-d,.175,0))
+      self.pad.append(point(-d,.175,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA4'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad,-d,.125,0))
+      self.pad.append(point(-d,.125,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA5'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad,-d,.075,0))
+      self.pad.append(point(-d,.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA6'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad,-d,.025,0))
+      self.pad.append(point(-d,.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA7'))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.025,0))
+      self.pad.append(point(-d,-.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB5'))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.075,0))
+      self.pad.append(point(-d,-.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB4'))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.125,0))
+      self.pad.append(point(-d,-.125,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RB3'))
+      #
+      # pin 9
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.175,0))
+      self.pad.append(point(-d,-.175,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'TB2'))
+      #
+      # pin 10
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.225,0))
+      self.pad.append(point(-d,-.225,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB1'))
+      #
+      # pin 11
+      #
+      self.shape = add(self.shape,translate(pad,d,-.225,0))
+      self.pad.append(point(d,-.225,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0'))
+      #
+      # pin 12
+      #
+      self.shape = add(self.shape,translate(pad,d,-.175,0))
+      self.pad.append(point(d,-.175,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC0'))
+      #
+      # pin 13
+      #
+      self.shape = add(self.shape,translate(pad,d,-.125,0))
+      self.pad.append(point(d,-.125,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC1'))
+      #
+      # pin 14
+      #
+      self.shape = add(self.shape,translate(pad,d,-.075,0))
+      self.pad.append(point(d,-.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC2'))
+      #
+      # pin 15
+      #
+      self.shape = add(self.shape,translate(pad,d,-.025,0))
+      self.pad.append(point(d,-.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC3'))
+      #
+      # pin 16
+      #
+      self.shape = add(self.shape,translate(pad,d,.025,0))
+      self.pad.append(point(d,.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'UPDI'))
+      #
+      # pin 17
+      #
+      self.shape = add(self.shape,translate(pad,d,.075,0))
+      self.pad.append(point(d,.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA1'))
+      #
+      # pin 18
+      #
+      self.shape = add(self.shape,translate(pad,d,.125,0))
+      self.pad.append(point(d,.125,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA2'))
+      #
+      # pin 19
+      #
+      self.shape = add(self.shape,translate(pad,d,.175,0))
+      self.pad.append(point(d,.175,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA3'))
+      #
+      # pin 20
+      #
+      self.shape = add(self.shape,translate(pad,d,.225,0))
+      self.pad.append(point(d,.225,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+
+class SAMD21E(part):
+   #
+   # TQFP
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      d = 9.01/2/25.4 # spacing
+      w = 0.4/2/25.4 # width
+      h = 1.4/2/25.4 # height
+      p = 0.8/25.4 # pitch
+      l = 0.004 # text
+      pad = cube(-h,h,-w,w,0,0)
+      padv = cube(-w,w,-h,h,0,0)
+      #
+      # pin 1
+      #
+      self.shape = translate(pad,-d,3.5*p,0)
+      self.shape = add(self.shape,cylinder(-d-h,3.5*p,0,0,w))
+      self.pad.append(point(-d,3.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1A0',line=l))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad,-d,2.5*p,0))
+      self.pad.append(point(-d,2.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A01',line=l))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad,-d,1.5*p,0))
+      self.pad.append(point(-d,1.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A02',line=l))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad,-d,.5*p,0))
+      self.pad.append(point(-d,.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A03',line=l))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.5*p,0))
+      self.pad.append(point(-d,-.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A04',line=l))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad,-d,-1.5*p,0))
+      self.pad.append(point(-d,-1.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A05',line=l))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad,-d,-2.5*p,0))
+      self.pad.append(point(-d,-2.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A06',line=l))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(pad,-d,-3.5*p,0))
+      self.pad.append(point(-d,-3.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A07',line=l))
+      #
+      # pin 9
+      #
+      self.shape = add(self.shape,translate(padv,-3.5*p,-d,0))
+      self.pad.append(point(-3.5*p,-d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VAN',line=l,angle=-90))
+      #
+      # pin 10
+      #
+      self.shape = add(self.shape,translate(padv,-2.5*p,-d,0))
+      self.pad.append(point(-2.5*p,-d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=l,angle=-90))
+      #
+      # pin 11
+      #
+      self.shape = add(self.shape,translate(padv,-1.5*p,-d,0))
+      self.pad.append(point(-1.5*p,-d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A08',line=l,angle=-90))
+      #
+      # pin 12
+      #
+      self.shape = add(self.shape,translate(padv,-.5*p,-d,0))
+      self.pad.append(point(-.5*p,-d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A09',line=l,angle=-90))
+      #
+      # pin 13
+      #
+      self.shape = add(self.shape,translate(padv,.5*p,-d,0))
+      self.pad.append(point(.5*p,-d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A10',line=l,angle=-90))
+      #
+      # pin 14
+      #
+      self.shape = add(self.shape,translate(padv,1.5*p,-d,0))
+      self.pad.append(point(1.5*p,-d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A11',line=l,angle=-90))
+      #
+      # pin 15
+      #
+      self.shape = add(self.shape,translate(padv,2.5*p,-d,0))
+      self.pad.append(point(2.5*p,-d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A14',line=l,angle=-90))
+      #
+      # pin 16
+      #
+      self.shape = add(self.shape,translate(padv,3.5*p,-d,0))
+      self.pad.append(point(3.5*p,-d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A15',line=l,angle=-90))
+      #
+      # pin 17
+      #
+      self.shape = add(self.shape,translate(pad,d,-3.5*p,0))
+      self.pad.append(point(d,-3.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A16',line=l))
+      #
+      # pin 18
+      #
+      self.shape = add(self.shape,translate(pad,d,-2.5*p,0))
+      self.pad.append(point(d,-2.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A17',line=l))
+      #
+      # pin 19
+      #
+      self.shape = add(self.shape,translate(pad,d,-1.5*p,0))
+      self.pad.append(point(d,-1.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A18',line=l))
+      #
+      # pin 20
+      #
+      self.shape = add(self.shape,translate(pad,d,-.5*p,0))
+      self.pad.append(point(d,-.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A19',line=l))
+      #
+      # pin 21
+      #
+      self.shape = add(self.shape,translate(pad,d,.5*p,0))
+      self.pad.append(point(d,.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A22',line=l))
+      #
+      # pin 22
+      #
+      self.shape = add(self.shape,translate(pad,d,1.5*p,0))
+      self.pad.append(point(d,1.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A23',line=l))
+      #
+      # pin 23
+      #
+      self.shape = add(self.shape,translate(pad,d,2.5*p,0))
+      self.pad.append(point(d,2.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'24-',line=l))
+      #
+      # pin 24
+      #
+      self.shape = add(self.shape,translate(pad,d,3.5*p,0))
+      self.pad.append(point(d,3.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'25+',line=l))
+      #
+      # pin 25
+      #
+      self.shape = add(self.shape,translate(padv,3.5*p,d,0))
+      self.pad.append(point(3.5*p,d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A27',line=l,angle=-90))
+      #
+      # pin 26
+      #
+      self.shape = add(self.shape,translate(padv,2.5*p,d,0))
+      self.pad.append(point(2.5*p,d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RST',line=l,angle=-90))
+      #
+      # pin 27
+      #
+      self.shape = add(self.shape,translate(padv,1.5*p,d,0))
+      self.pad.append(point(1.5*p,d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A28',line=l,angle=-90))
+      #
+      # pin 28
+      #
+      self.shape = add(self.shape,translate(padv,.5*p,d,0))
+      self.pad.append(point(.5*p,d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=l,angle=-90))
+      #
+      # pin 29
+      #
+      self.shape = add(self.shape,translate(padv,-.5*p,d,0))
+      self.pad.append(point(-.5*p,d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCR',line=l,angle=-90))
+      #
+      # pin 30
+      #
+      self.shape = add(self.shape,translate(padv,-1.5*p,d,0))
+      self.pad.append(point(-1.5*p,d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VIN',line=l,angle=-90))
+      #
+      # pin 31
+      #
+      self.shape = add(self.shape,translate(padv,-2.5*p,d,0))
+      self.pad.append(point(-2.5*p,d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CLK',line=l,angle=-90))
+      #
+      # pin 32
+      #
+      self.shape = add(self.shape,translate(padv,-3.5*p,d,0))
+      self.pad.append(point(-3.5*p,d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DIO',line=l,angle=-90))
+
+class SAMD11D(part):
+   #
+   # SOIC-20
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      d = 9.82/2/25.4
+      w = .63/2/25.4
+      h = 1.9/2/25.4
+      pad = cube(-h,h,-w,w,0,0)
+      #
+      # pin 1
+      #
+      self.shape = translate(pad,-d,.225,0)
+      self.shape = add(self.shape,cylinder(-d-h,.225,0,0,w))
+      self.pad.append(point(-d,.225,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1A05'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad,-d,.175,0))
+      self.pad.append(point(-d,.175,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A06'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad,-d,.125,0))
+      self.pad.append(point(-d,.125,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A07'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad,-d,.075,0))
+      self.pad.append(point(-d,.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A08'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad,-d,.025,0))
+      self.pad.append(point(-d,.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A09'))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.025,0))
+      self.pad.append(point(-d,-.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A14'))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.075,0))
+      self.pad.append(point(-d,-.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A15'))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.125,0))
+      self.pad.append(point(-d,-.125,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A16'))
+      #
+      # pin 9
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.175,0))
+      self.pad.append(point(-d,-.175,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A22'))
+      #
+      # pin 10
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.225,0))
+      self.pad.append(point(-d,-.225,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A23'))
+      #
+      # pin 11
+      #
+      self.shape = add(self.shape,translate(pad,d,-.225,0))
+      self.pad.append(point(d,-.225,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RST'))
+      #
+      # pin 12
+      #
+      self.shape = add(self.shape,translate(pad,d,-.175,0))
+      self.pad.append(point(d,-.175,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CLK'))
+      #
+      # pin 13
+      #
+      self.shape = add(self.shape,translate(pad,d,-.125,0))
+      self.pad.append(point(d,-.125,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DIO'))
+      #
+      # pin 14
+      #
+      self.shape = add(self.shape,translate(pad,d,-.075,0))
+      self.pad.append(point(d,-.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'24-'))
+      #
+      # pin 15
+      #
+      self.shape = add(self.shape,translate(pad,d,-.025,0))
+      self.pad.append(point(d,-.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'25+'))
+      #
+      # pin 16
+      #
+      self.shape = add(self.shape,translate(pad,d,.025,0))
+      self.pad.append(point(d,.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 17
+      #
+      self.shape = add(self.shape,translate(pad,d,.075,0))
+      self.pad.append(point(d,.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC'))
+      #
+      # pin 18
+      #
+      self.shape = add(self.shape,translate(pad,d,.125,0))
+      self.pad.append(point(d,.125,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A02'))
+      #
+      # pin 19
+      #
+      self.shape = add(self.shape,translate(pad,d,.175,0))
+      self.pad.append(point(d,.175,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A03'))
+      #
+      # pin 20
+      #
+      self.shape = add(self.shape,translate(pad,d,.225,0))
+      self.pad.append(point(d,.225,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A04'))
+
+class ATtiny1614(part):
+   #
+   # SOIC
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      d = 0.11
+      w = 0.015
+      h = .03
+      pad = cube(-h,h,-w,w,0,0)
+      #
+      # pin 1
+      #
+      self.shape = translate(pad,-d,.15,0)
+      self.shape = add(self.shape,cylinder(-d-h,.15,0,0,w))
+      self.pad.append(point(-d,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'.VCC'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad,-d,.1,0))
+      self.pad.append(point(-d,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA4'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad,-d,.050,0))
+      self.pad.append(point(-d,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA5'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad,-d,0,0))
+      self.pad.append(point(-d,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA6'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.05,0))
+      self.pad.append(point(-d,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA7'))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.1,0))
+      self.pad.append(point(-d,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RB3'))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.15,0))
+      self.pad.append(point(-d,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'TB2'))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(pad,d,-.15,0))
+      self.pad.append(point(d,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB1'))
+      #
+      # pin 9
+      #
+      self.shape = add(self.shape,translate(pad,d,-.1,0))
+      self.pad.append(point(d,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0'))
+      #
+      # pin 10
+      #
+      self.shape = add(self.shape,translate(pad,d,-.05,0))
+      self.pad.append(point(d,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'UPDI'))
+      #
+      # pin 11
+      #
+      self.shape = add(self.shape,translate(pad,d,0,0))
+      self.pad.append(point(d,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA1'))
+      #
+      # pin 12
+      #
+      self.shape = add(self.shape,translate(pad,d,.050,0))
+      self.pad.append(point(d,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA2'))
+      #
+      # pin 13
+      #
+      self.shape = add(self.shape,translate(pad,d,.1,0))
+      self.pad.append(point(d,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA3'))
+      #
+      # pin 14
+      self.shape = add(self.shape,translate(pad,d,.15,0))
+      self.pad.append(point(d,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+
+class FT230XS(part):
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      d = 0.11
+      w = 0.0053
+      h = .03
+      p = .65/25.4
+      l = 0.004
+      pad = cube(-h,h,-w,w,0,0)
+      #
+      # pin 1
+      #
+      self.shape = translate(pad,-d,3.5*p,0)
+      self.shape = add(self.shape,cylinder(-d-h,3.5*p,0,0,w))
+      self.pad.append(point(-d,3.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1TXD',line=l))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(pad,-d,2.5*p,0))
+      self.pad.append(point(-d,2.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RTS',line=l))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(pad,-d,1.5*p,0))
+      self.pad.append(point(-d,1.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VIO',line=l))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(pad,-d,.5*p,0))
+      self.pad.append(point(-d,.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RXD',line=l))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.5*p,0))
+      self.pad.append(point(-d,-.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=l))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(pad,-d,-1.5*p,0))
+      self.pad.append(point(-d,-1.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CTS',line=l))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(pad,-d,-2.5*p,0))
+      self.pad.append(point(-d,-2.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CB2',line=l))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(pad,-d,-3.5*p,0))
+      self.pad.append(point(-d,-3.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'USP',line=l))
+      #
+      # pin 9
+      #
+      self.shape = add(self.shape,translate(pad,d,-3.5*p,0))
+      self.pad.append(point(d,-3.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'USM',line=l))
+      #
+      # pin 10
+      #
+      self.shape = add(self.shape,translate(pad,d,-2.5*p,0))
+      self.pad.append(point(d,-2.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'3V3',line=l))
+      #
+      # pin 11
+      #
+      self.shape = add(self.shape,translate(pad,d,-1.5*p,0))
+      self.pad.append(point(d,-1.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RST',line=l))
+      #
+      # pin 12
+      #
+      self.shape = add(self.shape,translate(pad,d,-.5*p,0))
+      self.pad.append(point(d,-.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC',line=l))
+      #
+      # pin 13
+      #
+      self.shape = add(self.shape,translate(pad,d,.5*p,0))
+      self.pad.append(point(d,.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=l))
+      #
+      # pin 14
+      self.shape = add(self.shape,translate(pad,d,1.5*p,0))
+      self.pad.append(point(d,1.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CB1',line=l))
+      #
+      # pin 15
+      #
+      self.shape = add(self.shape,translate(pad,d,2.5*p,0))
+      self.pad.append(point(d,2.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CB0',line=l))
+      #
+      # pin 16
+      self.shape = add(self.shape,translate(pad,d,3.5*p,0))
+      self.pad.append(point(d,3.5*p,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CB3',line=l))
+
+
+class ATtiny412(part):
+   #
+   # SOIC150
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      d = 0.11
+      w = 0.015
+      h = .03
+      pad = cube(-h,h,-w,w,0,0)
+      #
+      # pin 1: VCC
+      #
+      self.shape = translate(pad,-d,.075,0)
+      self.shape = add(self.shape,cylinder(-d-h,.075,0,0,w))
+      self.pad.append(point(-d,.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC'))
+      #
+      # pin 2: PA6
+      #
+      self.shape = add(self.shape,translate(pad,-d,.025,0))
+      self.pad.append(point(-d,.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA6'))
+      #
+      # pin 3: PA7
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.025,0))
+      self.pad.append(point(-d,-.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA7'))
+      #
+      # pin 4: PA1
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.075,0))
+      self.pad.append(point(-d,-.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA1'))
+      #
+      # pin 5: PA2
+      #
+      self.shape = add(self.shape,translate(pad,d,-.075,0))
+      self.pad.append(point(d,-.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA2'))
+      #
+      # pin 6: UPDI
+      #
+      self.shape = add(self.shape,translate(pad,d,-.025,0))
+      self.pad.append(point(d,-.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'UPDI'))
+      #
+      # pin 7: PA3
+      #
+      self.shape = add(self.shape,translate(pad,d,.025,0))
+      self.pad.append(point(d,.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA3'))
+      #
+      # pin 8: GND
+      #
+      self.shape = add(self.shape,translate(pad,d,.075,0))
+      self.pad.append(point(d,.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+
+class SAMD11C(part):
+   #
+   # SOIC
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      d = 0.11
+      w = 0.015
+      h = .03
+      pad = cube(-h,h,-w,w,0,0)
+      #
+      # pin 1: PA05
+      #
+      self.shape = translate(pad,-d,.15,0)
+      self.shape = add(self.shape,cylinder(-d-h,.15,0,0,w))
+      self.pad.append(point(-d,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1A05'))
+      #
+      # pin 2: PA08
+      #
+      self.shape = add(self.shape,translate(pad,-d,.1,0))
+      self.pad.append(point(-d,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A08'))
+      #
+      # pin 3: PA09
+      #
+      self.shape = add(self.shape,translate(pad,-d,.050,0))
+      self.pad.append(point(-d,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A09'))
+      #
+      # pin 4: PA14
+      #
+      self.shape = add(self.shape,translate(pad,-d,0,0))
+      self.pad.append(point(-d,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A14'))
+      #
+      # pin 5: PA15
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.05,0))
+      self.pad.append(point(-d,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A15'))
+      #
+      # pin 6: nRESET
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.1,0))
+      self.pad.append(point(-d,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RST'))
+      #
+      # pin 7: CLK
+      #
+      self.shape = add(self.shape,translate(pad,-d,-.15,0))
+      self.pad.append(point(-d,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CLK'))
+      #
+      # pin 8: DIO
+      #
+      self.shape = add(self.shape,translate(pad,d,-.15,0))
+      self.pad.append(point(d,-.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DIO'))
+      #
+      # pin 9: PA24/D-
+      #
+      self.shape = add(self.shape,translate(pad,d,-.1,0))
+      self.pad.append(point(d,-.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'24-'))
+      #
+      # pin 10: PA25/D+
+      #
+      self.shape = add(self.shape,translate(pad,d,-.05,0))
+      self.pad.append(point(d,-.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'25+'))
+      #
+      # pin 11: GND
+      #
+      self.shape = add(self.shape,translate(pad,d,0,0))
+      self.pad.append(point(d,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 12: VDD
+      #
+      self.shape = add(self.shape,translate(pad,d,.050,0))
+      self.pad.append(point(d,.05,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VDD'))
+      #
+      # pin 13: PA02
+      #
+      self.shape = add(self.shape,translate(pad,d,.1,0))
+      self.pad.append(point(d,.1,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A02'))
+      #
+      # pin 14: PA04
+      #
+      self.shape = add(self.shape,translate(pad,d,.15,0))
+      self.pad.append(point(d,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A04'))
+
+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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'O'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V-'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'I+'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'I-'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V+'))
+
+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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1 Ao'))
+      #
+      # pin 2: A-
+      #
+      self.shape = add(self.shape,translate(pad_SOICN,-.12,.025,0))
+      self.pad.append(point(-.12,.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A-'))
+      #
+      # pin 3: A+
+      #
+      self.shape = add(self.shape,translate(pad_SOICN,-.12,-.025,0))
+      self.pad.append(point(-.12,-.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A+'))
+      #
+      # pin 4: V-
+      #
+      self.shape = add(self.shape,translate(pad_SOICN,-.12,-.075,0))
+      self.pad.append(point(-.12,-.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V-'))
+      #
+      # pin 5: B+
+      #
+      self.shape = add(self.shape,translate(pad_SOICN,.12,-.075,0))
+      self.pad.append(point(.12,-.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'B+'))
+      #
+      # pin 6: B-
+      #
+      self.shape = add(self.shape,translate(pad_SOICN,.12,-.025,0))
+      self.pad.append(point(.12,-.025,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'B-'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Bo'))
+      #
+      # pin 8: V+
+      #
+      self.shape = add(self.shape,translate(pad_SOICN,.12,.075,0))
+      self.pad.append(point(.12,.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'V+'))
+
+TSSOP_pad_width = 0.040
+TSSOP_pad_height = 0.011
+TSSOP_pad_dy = 0.026
+TSSOP_pad_dx = 0.120
+pad_TSSOP = cube(-TSSOP_pad_width/2.0,TSSOP_pad_width/2.0,-TSSOP_pad_height/2.0,TSSOP_pad_height/2.0,0,0)
+
+class TRC102(part):
+   #
+   # RFM TRC102 ISM transceiver
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: SDI
+      #
+      self.shape = translate(pad_TSSOP,-TSSOP_pad_dx,3.5*TSSOP_pad_dy,0)
+      self.pad.append(point(-TSSOP_pad_dx,3.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1 SDI'))
+      #
+      # pin 2: SCK
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,-TSSOP_pad_dx,2.5*TSSOP_pad_dy,0))
+      self.pad.append(point(-TSSOP_pad_dx,2.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCK'))
+      #
+      # pin 3: nCS
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,-TSSOP_pad_dx,1.5*TSSOP_pad_dy,0))
+      self.pad.append(point(-TSSOP_pad_dx,1.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'nCS'))
+      #
+      # pin 4: SDO
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,-TSSOP_pad_dx,0.5*TSSOP_pad_dy,0))
+      self.pad.append(point(-TSSOP_pad_dx,0.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SDO'))
+      #
+      # pin 5: IRQ
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,-TSSOP_pad_dx,-0.5*TSSOP_pad_dy,0))
+      self.pad.append(point(-TSSOP_pad_dx,-0.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IRQ'))
+      #
+      # pin 6: DATA/nFSEL
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,-TSSOP_pad_dx,-1.5*TSSOP_pad_dy,0))
+      self.pad.append(point(-TSSOP_pad_dx,-1.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DATA'))
+      #
+      # pin 7: CR
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,-TSSOP_pad_dx,-2.5*TSSOP_pad_dy,0))
+      self.pad.append(point(-TSSOP_pad_dx,-2.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CR'))
+      #
+      # pin 8: CLKOUT
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,-TSSOP_pad_dx,-3.5*TSSOP_pad_dy,0))
+      self.pad.append(point(-TSSOP_pad_dx,-3.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CLKOUT'))
+      #
+      # pin 9: Xtal/Ref
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,TSSOP_pad_dx,-3.5*TSSOP_pad_dy,0))
+      self.pad.append(point(TSSOP_pad_dx,-3.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Xtal'))
+      #
+      # pin 10: RESET
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,TSSOP_pad_dx,-2.5*TSSOP_pad_dy,0))
+      self.pad.append(point(TSSOP_pad_dx,-2.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RESET'))
+      #
+      # pin 11: GND
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,TSSOP_pad_dx,-1.5*TSSOP_pad_dy,0))
+      self.pad.append(point(TSSOP_pad_dx,-1.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 12: RF_P
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,TSSOP_pad_dx,-0.5*TSSOP_pad_dy,0))
+      self.pad.append(point(TSSOP_pad_dx,-0.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RF_P'))
+      #
+      # pin 13: RF_N
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,TSSOP_pad_dx,0.5*TSSOP_pad_dy,0))
+      self.pad.append(point(TSSOP_pad_dx,0.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RF_N'))
+      #
+      # pin 14: VDD
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,TSSOP_pad_dx,1.5*TSSOP_pad_dy,0))
+      self.pad.append(point(TSSOP_pad_dx,1.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VDD'))
+      #
+      # pin 15: RSSIA
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,TSSOP_pad_dx,2.5*TSSOP_pad_dy,0))
+      self.pad.append(point(TSSOP_pad_dx,2.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RSSIA'))
+      #
+      # pin 16: nINT/DDET
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,TSSOP_pad_dx,3.5*TSSOP_pad_dy,0))
+      self.pad.append(point(TSSOP_pad_dx,3.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'nINT'))
+
+pad_SOIC = cube(-.041,.041,-.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.shape = add(self.shape,cylinder(-.183,.075,0,0,.015))
+      self.pad.append(point(-.14,.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RST'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB3'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB4'))
+      #
+      # pin 4: GND
+      #
+      self.shape = add(self.shape,translate(pad_SOIC,-.14,-.075,0))
+      self.pad.append(point(-.14,-.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB1'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB2'))
+      #
+      # pin 8: VCC
+      #
+      self.shape = add(self.shape,translate(pad_SOIC,.14,.075,0))
+      self.pad.append(point(.14,.075,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC'))
+
+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.shape = add(self.shape,cylinder(-.155,.15,0,0,.015))
+      self.pad.append(point(-.12,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB1'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB3'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB2'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA7'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA6'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA5'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA4'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA3'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA2'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA1'))
+      #
+      # 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(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA0'))
+      #
+      # pin 14: GND
+      #
+      self.shape = add(self.shape,translate(pad_SOICN,.12,.15,0))
+      self.pad.append(point(.12,.15,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+
+pad_TQFP_h = cube(-.025,.025,-.007,.007,0,0)
+pad_TQFP_v = cube(-.007,.007,-.025,.025,0,0)
+
+class ATxmegaE5_TQFP(part):
+   def __init__(self,value=''):
+      c = .18
+      d = 0.8/25.4
+      s = 0.004
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: GND
+      #
+      self.shape = translate(pad_TQFP_h,-c,3.5*d,0)
+      self.pad.append(point(-c,3.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1 GND',line=s))
+      #
+      # pin 2: PA4
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,2.5*d,0))
+      self.pad.append(point(-c,2.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA4',line=s))
+      #
+      # pin 3: PA3
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,1.5*d,0))
+      self.pad.append(point(-c,1.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA3',line=s))
+      #
+      # pin 4: PA2
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,.5*d,0))
+      self.pad.append(point(-c,.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA2',line=s))
+      #
+      # pin 5: PA1
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,-.5*d,0))
+      self.pad.append(point(-c,-.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA1',line=s))
+      #
+      # pin 6: PA0
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,-1.5*d,0))
+      self.pad.append(point(-c,-1.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA0',line=s))
+      #
+      # pin 7: PDI/DATA
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,-2.5*d,0))
+      self.pad.append(point(-c,-2.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PDI/DATA',line=s))
+      #
+      # pin 8: RST/CLOCK
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,-3.5*d,0))
+      self.pad.append(point(-c,-3.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RST/CLOCK',line=s))
+      #
+      # pin 9: PC7
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-3.5*d,-c,0))
+      self.pad.append(point(-3.5*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC7',angle=90,line=s))
+      #
+      # pin 10: PC6
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-2.5*d,-c,0))
+      self.pad.append(point(-2.5*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC6',angle=90,line=s))
+      #
+      # pin 11: PC5
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-1.5*d,-c,0))
+      self.pad.append(point(-1.5*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC5',angle=90,line=s))
+      #
+      # pin 12: PC4
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-.5*d,-c,0))
+      self.pad.append(point(-.5*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC4',angle=90,line=s))
+      #
+      # pin 13: PC3
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,.5*d,-c,0))
+      self.pad.append(point(.5*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC3',angle=90,line=s))
+      #
+      # pin 14: PC2
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,1.5*d,-c,0))
+      self.pad.append(point(1.5*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC2',angle=90,line=s))
+      #
+      # pin 15: PC1
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,2.5*d,-c,0))
+      self.pad.append(point(2.5*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC1',angle=90,line=s))
+      #
+      # pin 16: PC0
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,3.5*d,-c,0))
+      self.pad.append(point(3.5*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC0',angle=90,line=s))
+      #
+      # pin 17: VCC
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,-3.5*d,0))
+      self.pad.append(point(c,-3.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC',line=s))
+      #
+      # pin 18: GND
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,-2.5*d,0))
+      self.pad.append(point(c,-2.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=s))
+      #
+      # pin 19: PR1
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,-1.5*d,0))
+      self.pad.append(point(c,-1.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PR1',line=s))
+      #
+      # pin 20: PR0
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,-.5*d,0))
+      self.pad.append(point(c,-.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PR0',line=s))
+      #
+      # pin 21: PD7
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,.5*d,0))
+      self.pad.append(point(c,.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD7',line=s))
+      #
+      # pin 22: PD6
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,1.5*d,0))
+      self.pad.append(point(c,1.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD6',line=s))
+      #
+      # pin 23: PD5
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,2.5*d,0))
+      self.pad.append(point(c,2.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD5',line=s))
+      #
+      # pin 24: PD4
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,3.5*d,0))
+      self.pad.append(point(c,3.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD4',line=s))
+      #
+      # pin 25: PD3
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,3.5*d,c,0))
+      self.pad.append(point(3.5*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD3',angle=90,line=s))
+      #
+      # pin 26: PD2
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,2.5*d,c,0))
+      self.pad.append(point(2.5*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD2',angle=90,line=s))
+      #
+      # pin 27: PD1
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,1.5*d,c,0))
+      self.pad.append(point(1.5*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD1',angle=90,line=s))
+      #
+      # pin 28: PD0
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,.5*d,c,0))
+      self.pad.append(point(.5*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD0',angle=90,line=s))
+      #
+      # pin 29: PA7
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-.5*d,c,0))
+      self.pad.append(point(-.5*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA7',angle=90,line=s))
+      #
+      # pin 30: PA6
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-1.5*d,c,0))
+      self.pad.append(point(-1.5*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA6',angle=90,line=s))
+      #
+      # pin 31: PA5
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-2.5*d,c,0))
+      self.pad.append(point(-2.5*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA5',angle=90,line=s))
+      #
+      # pin 32: AVCC
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-3.5*d,c,0))
+      self.pad.append(point(-3.5*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'AVCC',angle=90,line=s))
+
+class ATmega88_TQFP(part):
+   def __init__(self,value=''):
+      c = .18
+      d = .031
+      s = 0.004
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: PD3/PCINT19/OC2B/INT1
+      #
+      self.shape = translate(pad_TQFP_h,-c,3.5*d,0)
+      self.pad.append(point(-c,3.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1 PD3',line=s))
+      #
+      # pin 2: PD4/PCINT20/XCK/T0
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,2.5*d,0))
+      self.pad.append(point(-c,2.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD4',line=s))
+      #
+      # pin 3: GND
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,1.5*d,0))
+      self.pad.append(point(-c,1.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=s))
+      #
+      # pin 4: VCC
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,.5*d,0))
+      self.pad.append(point(-c,.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC',line=s))
+      #
+      # pin 5: GND
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,-.5*d,0))
+      self.pad.append(point(-c,-.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=s))
+      #
+      # pin 6: VCC
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,-1.5*d,0))
+      self.pad.append(point(-c,-1.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC',line=s))
+      #
+      # pin 7: PB6/PCINT6/XTAL1/TOSC1
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,-2.5*d,0))
+      self.pad.append(point(-c,-2.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB6',line=s))
+      #
+      # pin 8: PB7/PCINT7/XTAL2/TOSC2
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,-3.5*d,0))
+      self.pad.append(point(-c,-3.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB7',line=s))
+      #
+      # pin 9: PD5/PCINT21/OC0B/T1
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-3.5*d,-c,0))
+      self.pad.append(point(-3.5*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD5',angle=90,line=s))
+      #
+      # pin 10: PD6/PCINT22/OC0A/AIN0
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-2.5*d,-c,0))
+      self.pad.append(point(-2.5*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD6',angle=90,line=s))
+      #
+      # pin 11: PD7/PCINT23/AIN1
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-1.5*d,-c,0))
+      self.pad.append(point(-1.5*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD7',angle=90,line=s))
+      #
+      # pin 12: PB0/PCINT0/CLKO/ICP1
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-.5*d,-c,0))
+      self.pad.append(point(-.5*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0',angle=90,line=s))
+      #
+      # pin 13: PB1/PCINT1/OC1A
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,.5*d,-c,0))
+      self.pad.append(point(.5*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB1',angle=90,line=s))
+      #
+      # pin 14: PB2/PCINT2/-SS/OC1B
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,1.5*d,-c,0))
+      self.pad.append(point(1.5*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB2',angle=90,line=s))
+      #
+      # pin 15: PB3/PCINT3/OC2A/MOSI
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,2.5*d,-c,0))
+      self.pad.append(point(2.5*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB3',angle=90,line=s))
+      #
+      # pin 16: PB4/PCINT4/MISO
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,3.5*d,-c,0))
+      self.pad.append(point(3.5*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB4',angle=90,line=s))
+      #
+      # pin 17: PB5/SCK/PCINT5
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,-3.5*d,0))
+      self.pad.append(point(c,-3.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB5',line=s))
+      #
+      # pin 18: AVCC
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,-2.5*d,0))
+      self.pad.append(point(c,-2.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'AVCC',line=s))
+      #
+      # pin 19: ADC6
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,-1.5*d,0))
+      self.pad.append(point(c,-1.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'ADC6',line=s))
+      #
+      # pin 20: AREF
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,-.5*d,0))
+      self.pad.append(point(c,-.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'AREF',line=s))
+      #
+      # pin 21: GND
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,.5*d,0))
+      self.pad.append(point(c,.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=s))
+      #
+      # pin 22: ADC7
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,1.5*d,0))
+      self.pad.append(point(c,1.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'ADC7',line=s))
+      #
+      # pin 23: PC0/ADC0/PCINT8
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,2.5*d,0))
+      self.pad.append(point(c,2.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC0',line=s))
+      #
+      # pin 24: PC1/ADC1/PCINT9
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,3.5*d,0))
+      self.pad.append(point(c,3.5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC1',line=s))
+      #
+      # pin 25: PC2/ADC2/PCINT10
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,3.5*d,c,0))
+      self.pad.append(point(3.5*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC2',angle=90,line=s))
+      #
+      # pin 26: PC3/ADC3/PCINT11
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,2.5*d,c,0))
+      self.pad.append(point(2.5*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC3',angle=90,line=s))
+      #
+      # pin 27: PC4/ADC4/SDA/PCINT12
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,1.5*d,c,0))
+      self.pad.append(point(1.5*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC4',angle=90,line=s))
+      #
+      # pin 28: PC5/ADC5/SCL/PCINT13
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,.5*d,c,0))
+      self.pad.append(point(.5*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC5',angle=90,line=s))
+      #
+      # pin 29: PC6/-RESET/PCINT14
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-.5*d,c,0))
+      self.pad.append(point(-.5*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC6',angle=90,line=s))
+      #
+      # pin 30: PD0/RXD/PCINT16
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-1.5*d,c,0))
+      self.pad.append(point(-1.5*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD0',angle=90,line=s))
+      #
+      # pin 31: PD1/TXD/PCINT17
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-2.5*d,c,0))
+      self.pad.append(point(-2.5*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD1',angle=90,line=s))
+      #
+      # pin 32: PD2/INT0/PCINT18
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-3.5*d,c,0))
+      self.pad.append(point(-3.5*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD2',angle=90,line=s))
+
+class ATmega644_TQFP(part):
+   def __init__(self,value=''):
+      c = .235
+      d = .031
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: PB5/PCINT13/MOSI
+      #
+      self.shape = translate(pad_TQFP_h,-c,5*d,0)
+      self.pad.append(point(-c,5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'*MOSI (1)'))
+      #
+      # pin 2: PB6/PCINT14/MISO
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,4*d,0))
+      self.pad.append(point(-c,4*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'MISO'))
+      #
+      # pin 3: PB7/PCINT15/SCK
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,3*d,0))
+      self.pad.append(point(-c,3*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCK'))
+      #
+      # pin 4: -RESET
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,2*d,0))
+      self.pad.append(point(-c,2*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'-RESET'))
+      #
+      # pin 5: VCC
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,d,0))
+      self.pad.append(point(-c,d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC'))
+      #
+      # pin 6: GND
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,0,0))
+      self.pad.append(point(-c,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 7: XTAL2
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,-d,0))
+      self.pad.append(point(-c,-d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'XTAL2'))
+      #
+      # pin 8: XTAL1
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,-2*d,0))
+      self.pad.append(point(-c,-2*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'XTAL1'))
+      #
+      # pin 9: PD0/PCINT24/RXD0
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,-3*d,0))
+      self.pad.append(point(-c,-3*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RXD0'))
+      #
+      # pin 10: PD1/PCINT25/TXD0
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,-4*d,0))
+      self.pad.append(point(-c,-4*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'TXD0'))
+      #
+      # pin 11: PD2/PCINT26/INT0
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,-c,-5*d,0))
+      self.pad.append(point(-c,-5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD2'))
+      #
+      # pin 12: PD3/PCINT27/INT1
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-5*d,-c,0))
+      self.pad.append(point(-5*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD3'))
+      #
+      # pin 13: PD4/PCINT28/OC1B
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-4*d,-c,0))
+      self.pad.append(point(-4*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD4'))
+      #
+      # pin 14: PD5/PCINT28/OC1A
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-3*d,-c,0))
+      self.pad.append(point(-3*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD5'))
+      #
+      # pin 15: PD6/PCINT30/OC2B/ICP
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-2*d,-c,0))
+      self.pad.append(point(-2*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD6'))
+      #
+      # pin 16: PD7/PCINT31/OC2A
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-d,-c,0))
+      self.pad.append(point(-d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PD7'))
+      #
+      # pin 17: VCC
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,0,-c,0))
+      self.pad.append(point(0,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC'))
+      #
+      # pin 18: GND
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,d,-c,0))
+      self.pad.append(point(d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 19: PC0/PCINT16/SCL
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,2*d,-c,0))
+      self.pad.append(point(2*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC0'))
+      #
+      # pin 20: PC1/PCINT17/SDA
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,3*d,-c,0))
+      self.pad.append(point(3*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC1'))
+      #
+      # pin 21: PC2/PCINT18/TCK
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,4*d,-c,0))
+      self.pad.append(point(4*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC2'))
+      #
+      # pin 22: PC3/PCINT19/TMS
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,5*d,-c,0))
+      self.pad.append(point(5*d,-c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC3'))
+      #
+      # pin 23: PC4/TDO/PCINT20
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,-5*d,0))
+      self.pad.append(point(c,-5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC4'))
+      #
+      # pin 24: PC5/TDI/PCINT21
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,-4*d,0))
+      self.pad.append(point(c,-4*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC5'))
+      #
+      # pin 25: PC6/TOSC1/PCINT22
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,-3*d,0))
+      self.pad.append(point(c,-3*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC6'))
+      #
+      # pin 26: PC7/TOSC2/PCINT23
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,-2*d,0))
+      self.pad.append(point(c,-2*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PC7'))
+      #
+      # pin 27: AVCC
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,-d,0))
+      self.pad.append(point(c,-d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'AVCC'))
+      #
+      # pin 28: GND
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,0,0))
+      self.pad.append(point(c,0,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 29: AREF
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,d,0))
+      self.pad.append(point(c,d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'AREF'))
+      #
+      # pin 30: PA7/ADC7/PCINT7
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,2*d,0))
+      self.pad.append(point(c,2*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA7'))
+      #
+      # pin 31: PA6/ADC6/PCINT6
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,3*d,0))
+      self.pad.append(point(c,3*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA6'))
+      #
+      # pin 32: PA5/ADC5/PCINT5
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,4*d,0))
+      self.pad.append(point(c,4*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA5'))
+      #
+      # pin 33: PA4/ADC4/PCINT4
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_h,c,5*d,0))
+      self.pad.append(point(c,5*d,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA4'))
+      #
+      # pin 34: PA3/ADC3/PCINT3
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,5*d,c,0))
+      self.pad.append(point(5*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA3'))
+      #
+      # pin 35: PA2/ADC2/PCINT2
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,4*d,c,0))
+      self.pad.append(point(4*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA2'))
+      #
+      # pin 36: PA1/ADC1/PCINT1
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,3*d,c,0))
+      self.pad.append(point(3*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA1'))
+      #
+      # pin 37: PA0/ADC0/PCINT0
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,2*d,c,0))
+      self.pad.append(point(2*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PA0'))
+      #
+      # pin 38: VCC
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,d,c,0))
+      self.pad.append(point(d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC'))
+      #
+      # pin 39: GND
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,0,c,0))
+      self.pad.append(point(0,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 40: PB0/XCK0/T0/PCINT8
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-d,c,0))
+      self.pad.append(point(-d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0'))
+      #
+      # pin 41: PB1/T1/CLKO/PCINT9
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-2*d,c,0))
+      self.pad.append(point(-2*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB1'))
+      #
+      # pin 42: PB2/AIN0/INT2/PCINT10
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-3*d,c,0))
+      self.pad.append(point(-3*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB2'))
+      #
+      # pin 43: PB3/AIN1/OC0A/PCINT11
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-4*d,c,0))
+      self.pad.append(point(-4*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB2'))
+      #
+      # pin 44: PB4/-SS/OC0B/PCINT12
+      #
+      self.shape = add(self.shape,translate(pad_TQFP_v,-5*d,c,0))
+      self.pad.append(point(-5*d,c,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB4'))
+
+TSSOP_pad_width = 0.040
+TSSOP_pad_height = 0.011
+TSSOP_pad_dy = 0.026
+TSSOP_pad_dx = 0.120
+pad_TSSOP = cube(-TSSOP_pad_width/2.0,TSSOP_pad_width/2.0,-TSSOP_pad_height/2.0,TSSOP_pad_height/2.0,0,0)
+
+class TRC102(part):
+   #
+   # RFM TRC102 ISM transceiver
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1: SDI
+      #
+      self.shape = translate(pad_TSSOP,-TSSOP_pad_dx,3.5*TSSOP_pad_dy,0)
+      self.pad.append(point(-TSSOP_pad_dx,3.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1 SDI'))
+      #
+      # pin 2: SCK
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,-TSSOP_pad_dx,2.5*TSSOP_pad_dy,0))
+      self.pad.append(point(-TSSOP_pad_dx,2.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SCK'))
+      #
+      # pin 3: nCS
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,-TSSOP_pad_dx,1.5*TSSOP_pad_dy,0))
+      self.pad.append(point(-TSSOP_pad_dx,1.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'nCS'))
+      #
+      # pin 4: SDO
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,-TSSOP_pad_dx,0.5*TSSOP_pad_dy,0))
+      self.pad.append(point(-TSSOP_pad_dx,0.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'SDO'))
+      #
+      # pin 5: IRQ
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,-TSSOP_pad_dx,-0.5*TSSOP_pad_dy,0))
+      self.pad.append(point(-TSSOP_pad_dx,-0.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'IRQ'))
+      #
+      # pin 6: DATA/nFSEL
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,-TSSOP_pad_dx,-1.5*TSSOP_pad_dy,0))
+      self.pad.append(point(-TSSOP_pad_dx,-1.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DATA'))
+      #
+      # pin 7: CR
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,-TSSOP_pad_dx,-2.5*TSSOP_pad_dy,0))
+      self.pad.append(point(-TSSOP_pad_dx,-2.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CR'))
+      #
+      # pin 8: CLKOUT
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,-TSSOP_pad_dx,-3.5*TSSOP_pad_dy,0))
+      self.pad.append(point(-TSSOP_pad_dx,-3.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'CLKOUT'))
+      #
+      # pin 9: Xtal/Ref
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,TSSOP_pad_dx,-3.5*TSSOP_pad_dy,0))
+      self.pad.append(point(TSSOP_pad_dx,-3.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Xtal'))
+      #
+      # pin 10: RESET
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,TSSOP_pad_dx,-2.5*TSSOP_pad_dy,0))
+      self.pad.append(point(TSSOP_pad_dx,-2.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RESET'))
+      #
+      # pin 11: GND
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,TSSOP_pad_dx,-1.5*TSSOP_pad_dy,0))
+      self.pad.append(point(TSSOP_pad_dx,-1.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND'))
+      #
+      # pin 12: RF_P
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,TSSOP_pad_dx,-0.5*TSSOP_pad_dy,0))
+      self.pad.append(point(TSSOP_pad_dx,-0.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RF_P'))
+      #
+      # pin 13: RF_N
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,TSSOP_pad_dx,0.5*TSSOP_pad_dy,0))
+      self.pad.append(point(TSSOP_pad_dx,0.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RF_N'))
+      #
+      # pin 14: VDD
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,TSSOP_pad_dx,1.5*TSSOP_pad_dy,0))
+      self.pad.append(point(TSSOP_pad_dx,1.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VDD'))
+      #
+      # pin 15: RSSIA
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,TSSOP_pad_dx,2.5*TSSOP_pad_dy,0))
+      self.pad.append(point(TSSOP_pad_dx,2.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'RSSIA'))
+      #
+      # pin 16: nINT/DDET
+      #
+      self.shape = add(self.shape,translate(pad_TSSOP,TSSOP_pad_dx,3.5*TSSOP_pad_dy,0))
+      self.pad.append(point(TSSOP_pad_dx,3.5*TSSOP_pad_dy,0))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'nINT'))
+
+class CBA(part):
+   #
+   # CBA logo
+   #
+   def __init__(self,r=.02):
+      self.value = ''
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      d = 3*r
+      self.shape = cylinder(0,0,0,0,r)
+      self.shape = add(self.shape,translate(cylinder(0,0,0,0,r),-d,d,0))
+      self.shape = add(self.shape,translate(cube(-r,r,-r,r,0,0),-d,0,0))
+      self.shape = add(self.shape,translate(cube(-r,r,-r,r,0,0),-d,-d,0))
+      self.shape = add(self.shape,translate(cube(-r,r,-r,r,0,0),0,-d,0))
+      self.shape = add(self.shape,translate(cube(-r,r,-r,r,0,0),d,-d,0))
+      self.shape = add(self.shape,translate(cube(-r,r,-r,r,0,0),d,0,0))
+      self.shape = add(self.shape,translate(cube(-r,r,-r,r,0,0),d,d,0))
+      self.shape = add(self.shape,translate(cube(-r,r,-r,r,0,0),0,d,0))
+
+class fab(part):
+   def __init__(self,r=.05):
+      self.value = ''
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      d = 1.8*r
+      l = 3.5*r
+      h = r/2.
+      self.shape = rectangle(-d,d,-d,d)
+      self.shape = subtract(self.shape,circle(0,0,r))
+      self.shape = subtract(self.shape,rectangle(-l,0,-h,h))
+      self.shape = add(self.shape,rectangle(d,l,-h,h))
+      self.shape = add(self.shape,circle(l,0,r))
+      self.shape = add(self.shape,circle(-l,0,r))
+
+############################################################
+# define board
+############################################################
+
+width = 1.99 # board width
+height = 1.99-.34 # board height
+x = 1 # x origin
+y = 1 # y origin
+zt = 0 # top z
+zb = -0.06 # bottom z
+w = .0106 # wire width
+w1 = .015 # thicker wire width
+w2 = .03 # thickest wire width
+mask = .002 # solder mask size
+
+pcb = PCB(x,y,width,height,mask)
+
+IC1 = DRV8428P_HTSSOP('IC1\nDRV8428P')
+pcb = IC1.add(pcb,x+.56,y+height/2+.25)
+
+pcb = wire(pcb,w,
+   IC1.pad[2],
+   point(IC1.x,IC1.pad[2].y))
+
+pcb = wire(pcb,w,
+   IC1.pad[2],
+   point(IC1.pad[2].x-.075,IC1.pad[2].y))
+
+pcb = wire(pcb,w,
+   IC1.pad[7],
+   point(IC1.x,IC1.pad[7].y))
+
+pcb = wire(pcb,w,
+   IC1.pad[7],
+   point(IC1.pad[7].x-.075,IC1.pad[7].y))
+
+pcb = wire(pcb,w,
+   IC1.pad[9],
+   point(IC1.pad[9].x+.075,IC1.pad[9].y))
+
+pcb = wire(pcb,w,
+   IC1.pad[10],
+   point(IC1.pad[10].x+.075,IC1.pad[10].y))
+
+pcb = wire(pcb,w,
+   point(IC1.pad[9].x+.075,IC1.pad[9].y),
+   point(IC1.pad[10].x+.075,IC1.pad[10].y))
+
+pcb = wire(pcb,w,
+   IC1.pad[11],
+   point(IC1.x,IC1.pad[11].y))
+
+pcb = wire(pcb,w,
+   IC1.pad[11],
+   point(IC1.pad[11].x+.075,IC1.pad[11].y))
+
+J2 = header_4H('J2\nstepper')
+pcb = J2.add(pcb,x+.23,y+height/2,angle=180)
+
+pcb = wire(pcb,w,
+   IC1.pad[3],
+   point(J2.x-.132,IC1.pad[3].y),
+   point(J2.x-.132,J2.pad[1].y),
+   J2.pad[1])
+
+pcb = wire(pcb,w,
+   IC1.pad[4],
+   point(J2.x-.106,IC1.pad[4].y),
+   point(J2.x-.106,J2.pad[2].y),
+   J2.pad[2])
+
+pcb = wire(pcb,w,
+   IC1.pad[5],
+   point(J2.x-.08,IC1.pad[5].y),
+   point(J2.x-.08,J2.pad[3].y),
+   J2.pad[3])
+
+pcb = wire(pcb,w,
+   IC1.pad[6],
+   point(J2.x,IC1.pad[6].y),
+   J2.pad[4])
+
+R1 = ST4EB('R1\n10k')
+pcb = R1.add(pcb,IC1.x-.05,IC1.y-.35)
+
+pcb = wire(pcb,w,
+   IC1.pad[9],
+   point(IC1.pad[9].x,IC1.pad[9].y-.06),
+   point(R1.pad[3].x,IC1.pad[9].y-.06),
+   R1.pad[3])
+
+C1 = C_1206('C1\n1uF')
+pcb = C1.add(pcb,J2.x,J2.pad[1].y-.16,angle=90)
+
+pcb = wire(pcb,w1,
+   C1.pad[1],
+   point(C1.x,y+.37))
+
+pcb = wire(pcb,w,
+   C1.pad[2],
+   point(C1.x+.1,C1.pad[2].y),
+   point(C1.x+.1,IC1.pad[8].y),
+   IC1.pad[8])
+
+R2 = R_1206('R2\n10k')
+pcb = R2.add(pcb,R1.pad[1].x-.02,R1.y-.24,angle=0)
+
+pcb = wire(pcb,w,
+   R2.pad[1],
+   point(R2.pad[1].x,C1.pad[2].y),
+   C1.pad[2])
+
+pcb = wire(pcb,w1,
+   R2.pad[2],
+   point(R1.pad[1].x,R2.y),
+   R1.pad[1])
+
+C2 = C_FND('C2\n100uF')
+pcb = C2.add(pcb,IC1.x+.08,IC1.y+.27,angle=90)
+
+pcb = wire(pcb,w2,
+   C2.pad[2],
+   point(C2.pad[2].x,C2.y-.08))
+
+J4 = header_2H('J4\npower')
+pcb = J4.add(pcb,x+.23,IC1.pad[1].y+.05,angle=180)
+
+pcb = wire(pcb,w,
+   IC1.pad[1],
+   point(J4.x,IC1.pad[1].y))
+
+pcb = wire(pcb,w,
+   IC1.pad[1],
+   point(IC1.pad[1].x+.025,IC1.pad[1].y),
+   point(IC1.pad[1].x+.025,IC1.pad[1].y+w),
+   point(J4.x,IC1.pad[1].y+w))
+
+pcb = wire(pcb,w2,
+   point(C2.pad[1].x-.02,C2.y),
+   point(J4.x+.10,J4.pad[1].y+.01),
+   point(J4.x,J4.pad[1].y+.01),
+   J4.pad[1])
+
+C3 = C_1206('C3\n.01uF')
+pcb = C3.add(pcb,C2.x+.31,C2.y)
+
+pcb = wire(pcb,w2,
+   C2.pad[2],
+   C3.pad[1])
+
+pcb = wire(pcb,w2,
+   C3.pad[2],
+   point(C3.pad[2].x,C3.y+.08),
+   point(C2.pad[1].x,C3.y+.08),
+   C2.pad[1])
+
+IC2 = SAMD11C('IC2\nD11C')
+pcb = IC2.add(pcb,x+width-.62,y+height/2,angle=-90)
+
+J1 = header_SWD_4_1('J1 SWD')
+pcb = J1.add(pcb,IC2.pad[7].x-.14,IC2.y,angle=-90)
+
+pcb = wire(pcb,w1,
+   J1.pad[1],
+   point(J1.pad[1].x,IC2.pad[7].y),
+   IC2.pad[7])
+
+pcb = wire(pcb,w1,
+   J1.pad[2],
+   point(J1.pad[2].x,IC2.pad[8].y),
+   IC2.pad[8])
+
+pcb = wire(pcb,w,
+   J1.pad[3],
+   point(J1.pad[3].x,IC2.pad[6].y+.08),
+   point(IC2.pad[6].x,IC2.pad[6].y+.08),
+   IC2.pad[6])
+
+pcb = wire(pcb,w1,
+   J1.pad[4],
+   point(J1.pad[4].x,IC2.pad[12].y-.08),
+   point(IC2.pad[11].x,IC2.pad[11].y-.08),
+   IC2.pad[11])
+
+pcb = wire(pcb,w1,
+   J1.pad[4],
+   point(J1.pad[4].x,IC2.pad[12].y-.08),
+   point(R1.pad[2].x,IC2.pad[12].y-.08),
+   R1.pad[2])
+
+pcb = wire(pcb,w,
+   IC2.pad[1],
+   point(IC2.pad[1].x,IC1.pad[16].y),
+   IC1.pad[16])
+
+pcb = wire(pcb,w,
+   IC2.pad[2],
+   point(IC2.pad[2].x,IC1.pad[15].y),
+   IC1.pad[15])
+
+pcb = wire(pcb,w,
+   IC2.pad[3],
+   point(IC2.pad[3].x,IC1.pad[14].y),
+   IC1.pad[14])
+
+pcb = wire(pcb,w,
+   IC2.pad[4],
+   point(IC2.pad[4].x,IC1.pad[13].y),
+   IC1.pad[13])
+
+pcb = wire(pcb,w,
+   IC2.pad[5],
+   point(IC2.pad[5].x,IC1.pad[12].y),
+   IC1.pad[12])
+
+J3 = USB_A_plug('J3\nUSB')
+pcb = J3.add(pcb,x+width-.29,IC2.y+.025,angle=0)
+
+pcb = wire(pcb,w1,
+   J3.pad[2],
+   point(J3.pad[2].x-.11,J3.pad[2].y),
+   point(J3.pad[2].x-.11,IC2.y+.015),
+   point(IC2.pad[9].x,IC2.y+.015),
+   IC2.pad[9])
+
+pcb = wire(pcb,w1,
+   point(J3.pad[3].x,IC2.y-.015),
+   point(IC2.pad[10].x,IC2.y-.015),
+   IC2.pad[10])
+
+pcb = wire(pcb,w1,
+   J3.pad[4],
+   point(J3.pad[4].x-.11,J3.pad[4].y),
+   point(J3.pad[4].x-.11,IC2.y-.045),
+   point(IC2.pad[11].x,IC2.y-.045),
+   IC2.pad[11])
+
+pcb = wire(pcb,w2,
+   J3.pad[4],
+   point(J3.pad[4].x-.11,J3.pad[4].y),
+   point(J3.pad[4].x-.11,y+.37),
+   point(x+.03,y+.37),
+   point(x+.03,J4.pad[2].y),
+   J4.pad[2])
+
+IC3 = regulator_SOT23('IC3\n3.3V')
+pcb = IC3.add(pcb,IC2.pad[8].x-.1,IC2.pad[9].y-.21,angle=0)
+
+pcb = wire(pcb,w1,
+   J4.pad[1],
+   point(x+.07,J4.pad[1].y),
+   point(x+.07,C1.y),
+   point(C1.x+.08,C1.y),
+   point(C1.x+.08,IC3.pad[2].y-.05),
+   point(IC3.pad[2].x,IC3.pad[2].y-.05),
+   IC3.pad[2])
+
+pcb = wire(pcb,w1,
+   IC3.pad[3],
+   point(IC3.pad[3].x,y+.37))
+
+C4 = C_1206('C4\n1uF')
+pcb = C4.add(pcb,IC3.x-.22,IC3.y)
+
+pcb = wire(pcb,w1,
+   C4.pad[1],
+   point(C4.pad[1].x,C4.y+.1),
+   point(IC3.pad[1].x,C4.y+.1),
+   IC3.pad[1])
+
+pcb = wire(pcb,w1,
+   C4.pad[2],
+   IC3.pad[3])
+
+pcb = wire(pcb,w1,
+   IC3.pad[1],
+   point(IC3.pad[1].x,C4.y+.1),
+   point(IC2.pad[12].x,C4.y+.1),
+   IC2.pad[12])
+
+R3 = R_1206('R3\n0')
+pcb = R3.add(pcb,C3.x+.22,C3.y)
+
+pcb = wire(pcb,w2,
+   C3.pad[2],
+   R3.pad[1])
+
+pcb = wire(pcb,w2,
+   R3.pad[2],
+   point(R3.pad[2].x+.07,R3.pad[2].y),
+   point(R3.pad[2].x+.12,J4.pad[2].y),
+   point(J3.pad[4].x-.11,J4.pad[2].y),
+   point(J3.pad[4].x-.11,J3.pad[1].y),
+   J3.pad[1])
+
+pcb = wire(pcb,w2,
+   IC1.pad[17],
+   point(IC1.x,R3.y-.13),
+   point(IC1.x+.04,R3.y-.08),
+   point(R3.x,R3.y-.08))
+
+pcb = wire(pcb,w2,
+   J4.pad[2],
+   point(J4.x+.11,J4.pad[2].y),
+   point(J4.x+.17,J4.pad[2].y+.06),
+   point(J4.x+.17,C2.y+.07),
+   point(J4.x+.23,C2.y+.13),
+   point(R3.x,C2.y+.13))
+
+pcb = wire(pcb,w1,
+   point(R3.x,R3.y-.08),
+   point(R3.x,C2.y+.13))
+
+R4 = R_1206('R4\n1k')
+pcb = R4.add(pcb,IC2.pad[11].x+.01,IC3.y+.03,angle=0)
+
+pcb = wire(pcb,w1,
+   R4.pad[2],
+   point(IC2.pad[13].x,R4.y),
+   IC2.pad[13])
+
+LED = LED_1206('LED')
+pcb = LED.add(pcb,R4.x,R4.y-.09,angle=180)
+
+pcb = wire(pcb,w1,
+   LED.pad[1],
+   point(IC2.pad[14].x,LED.y),
+   IC2.pad[14])
+
+pcb = wire(pcb,w1,
+   LED.pad[2],
+   point(R4.pad[1].x,LED.y),
+   R4.pad[1])
+
+pcb.holes = add(pcb.holes,cylinder(x+(width-.34)/2,y+height/2,zb,zt,.125))
+pcb.holes = add(pcb.holes,cylinder(x+.21,y+height-.21,zb,zt,.065))
+pcb.holes = add(pcb.holes,cylinder(x+.21,y+.21,zb,zt,.065))
+pcb.holes = add(pcb.holes,cylinder(x+width-(.21+.34),y+height-.21,zb,zt,.065))
+pcb.holes = add(pcb.holes,cylinder(x+width-(.21+.34),y+.21,zb,zt,.065))
+
+l = 0.13
+pcb.exterior = add(pcb.exterior,triangle(x,y+height-l,x,y+height,x+l,y+height))
+pcb.exterior = add(pcb.exterior,triangle(x,y,x,y+l,x+l,y))
+pcb.exterior = add(pcb.exterior,triangle(x+width-.34,y+height,x+width-.34,y+height-l,x+width-l-.34,y+height))
+pcb.exterior = add(pcb.exterior,triangle(x+width-.34-l,y,x+width-.34,y+l,x+width-.34,y))
+pcb.interior = subtract(pcb.interior,triangle(x,y+height-l,x,y+height,x+l,y+height))
+pcb.interior = subtract(pcb.interior,triangle(x,y,x,y+l,x+l,y))
+pcb.interior = subtract(pcb.interior,triangle(x+width-.34,y+height,x+width-.34,y+height-l,x+width-l-.34,y+height))
+pcb.interior = subtract(pcb.interior,triangle(x+width-.34-l,y,x+width-.34,y+l,x+width-.34,y))
+
+#pcb.exterior = add(pcb.exterior,text("8/20/21",x+(width-.34)/2+.1,y+0.2,0,line=0.01,color=White).shape)
+#pcb.exterior = add(pcb.exterior,text("hello.DRV8428P-D11C-NEMA17",x+(width-.34)/2,y+0.075,0,line=0.01,color=White).shape)
+#c = CBA(r=0.0125)
+#pcb.exterior = add(pcb.exterior,move(c.shape,x+(width-.34)/2-.175,y+.2))
+
+############################################################
+# select output
+############################################################
+
+outputs = {}
+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, labels, holes, and exterior"):
+   outputs["function"] = add(add(color(Tan,pcb.board),pcb.labels),
+      add(color(White,pcb.exterior),color(Blue,pcb.holes)))
+   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,pcb.board),pcb.labels),
+      add(color(White,pcb.exterior),color(Blue,pcb.holes)))
+   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"] = [zt]
+elif (output == "exterior"):
+   outputs["function"] = color(White,pcb.exterior)
+   outputs["layers"] = [zt]
+elif (output == "holes"):
+   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")
+
+############################################################
+# set limits and parameters
+############################################################
+
+border = 0.05
+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["mm_per_unit"] = 25.4 # use inch units
+outputs["type"] = "RGB" # use RGB color
+
+############################################################
+# send output
+############################################################
+
+json.dump(outputs,sys.stdout)
diff --git a/serialstep/serialstep-DRV8428P/board/hello.DRV8428P-D11C-NEMA17.holes.png b/serialstep/serialstep-DRV8428P/board/hello.DRV8428P-D11C-NEMA17.holes.png
new file mode 100644
index 0000000000000000000000000000000000000000..e14ffbb3b6535677ad7f97e16cecca0dbea76366
GIT binary patch
literal 21455
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
R-B<x~qNl5$%Q~loCICC0+qnP$

literal 0
HcmV?d00001

diff --git a/serialstep/serialstep-DRV8428P/board/hello.DRV8428P-D11C-NEMA17.interior.png b/serialstep/serialstep-DRV8428P/board/hello.DRV8428P-D11C-NEMA17.interior.png
new file mode 100644
index 0000000000000000000000000000000000000000..34acd3b421bc48e61cefc9f943f06bc0e6c0d7d6
GIT binary patch
literal 20296
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

literal 0
HcmV?d00001

diff --git a/serialstep/serialstep-DRV8428P/board/hello.DRV8428P-D11C-NEMA17.png b/serialstep/serialstep-DRV8428P/board/hello.DRV8428P-D11C-NEMA17.png
new file mode 100644
index 0000000000000000000000000000000000000000..0b0723c90a086ea02e143137f5cd0323ce197a06
GIT binary patch
literal 56114
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%0D5cFV4=
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

literal 0
HcmV?d00001

diff --git a/serialstep/serialstep-DRV8428P/board/hello.DRV8428P-D11C-NEMA17.traces.png b/serialstep/serialstep-DRV8428P/board/hello.DRV8428P-D11C-NEMA17.traces.png
new file mode 100644
index 0000000000000000000000000000000000000000..c663ae1f619bab07e75a27afd73a710455b50e5f
GIT binary patch
literal 23212
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
N44$rjF6*2UngEp_*&+Y{

literal 0
HcmV?d00001

-- 
GitLab