From 9477dd872cd1f48e5c6cf52efee59dc73367db9c Mon Sep 17 00:00:00 2001
From: Quentin Bolsee <quentinbolsee@hotmail.com>
Date: Wed, 30 Nov 2022 14:24:58 -0500
Subject: [PATCH] images

---
 .gitignore                                    |    1 +
 README.md                                     |   20 +-
 adc_10k/README.md                             |   32 +
 .../code/serialadc/serialadc.ino              |   16 +-
 adc_10k/hello.ADC10k-D11C                     | 8203 ++++++++++++++++
 .../img/D11C.ADC10k.components.jpg            |  Bin
 .../img/D11C.pressure.components.bottom.jpg   |  Bin
 .../img/D11C.pressure.components.top.jpg      |  Bin
 adc_10k/img/hello.ADC10k-D11C.board.png       |  Bin 0 -> 22936 bytes
 adc_10k/img/hello.ADC10k-D11C.interior.png    |  Bin 0 -> 6883 bytes
 adc_10k/img/hello.ADC10k-D11C.traces.png      |  Bin 0 -> 8411 bytes
 .../img/hello.ADC10k-D11C.traces_exterior.png |  Bin 0 -> 8448 bytes
 capacitive/README.md                          |   18 +-
 .../serialcapa.ino}                           |   15 +-
 distance/README.md                            |    2 +-
 .../serial_hcsr04.ino}                        |   16 +-
 mosfet/README.md                              |   30 +-
 mosfet/code/serialnmos/serialnmos.ino         |   41 +
 mosfet/hello.NMOS-D11C                        | 8255 +++++++++++++++++
 mosfet/img/hello.NMOS-D11C.board.png          |  Bin 0 -> 28854 bytes
 mosfet/img/hello.NMOS-D11C.interior.png       |  Bin 0 -> 9526 bytes
 mosfet/img/hello.NMOS-D11C.traces.png         |  Bin 0 -> 11788 bytes
 .../img/hello.NMOS-D11C.traces_exterior.png   |  Bin 0 -> 11846 bytes
 potentiometer/README.md                       |    2 +-
 .../d11_pot.ino => serialpot/serialpot.ino}   |   17 +-
 thermistor-or-pressure/README.md              |   17 -
 26 files changed, 16642 insertions(+), 43 deletions(-)
 create mode 100644 .gitignore
 create mode 100644 adc_10k/README.md
 rename thermistor-or-pressure/code/d11_pressure/d11_pressure.ino => adc_10k/code/serialadc/serialadc.ino (69%)
 create mode 100644 adc_10k/hello.ADC10k-D11C
 rename thermistor-or-pressure/img/D11C.10k.ADC.components.jpg => adc_10k/img/D11C.ADC10k.components.jpg (100%)
 rename {thermistor-or-pressure => adc_10k}/img/D11C.pressure.components.bottom.jpg (100%)
 rename {thermistor-or-pressure => adc_10k}/img/D11C.pressure.components.top.jpg (100%)
 create mode 100644 adc_10k/img/hello.ADC10k-D11C.board.png
 create mode 100644 adc_10k/img/hello.ADC10k-D11C.interior.png
 create mode 100644 adc_10k/img/hello.ADC10k-D11C.traces.png
 create mode 100644 adc_10k/img/hello.ADC10k-D11C.traces_exterior.png
 rename capacitive/code/{d11_capa/d11_capa.ino => serialcapa/serialcapa.ino} (74%)
 rename distance/code/{d11_distance/d11_distance.ino => serial_hcsr04/serial_hcsr04.ino} (77%)
 create mode 100644 mosfet/code/serialnmos/serialnmos.ino
 create mode 100644 mosfet/hello.NMOS-D11C
 create mode 100644 mosfet/img/hello.NMOS-D11C.board.png
 create mode 100644 mosfet/img/hello.NMOS-D11C.interior.png
 create mode 100644 mosfet/img/hello.NMOS-D11C.traces.png
 create mode 100644 mosfet/img/hello.NMOS-D11C.traces_exterior.png
 rename potentiometer/code/{d11_pot/d11_pot.ino => serialpot/serialpot.ino} (62%)
 delete mode 100644 thermistor-or-pressure/README.md

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..1579b8f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+triage/*
diff --git a/README.md b/README.md
index 114ba74..a07d8be 100644
--- a/README.md
+++ b/README.md
@@ -4,34 +4,34 @@
 
 ### [Capacitive input](./capacitive)
 
-<img src=./capacitive/img/D11C.capacitive.components.top.jpg width=65%><br>
+<img src=./capacitive/img/D11C.capacitive.components.top.jpg width=45%><br>
 
 ### [Distance input](./distance)
 
-<img src=./distance/img/D11C.distance.components.top.jpg width=65%><br>
+<img src=./distance/img/D11C.distance.components.top.jpg width=45%><br>
 
-<img src=./distance/img/D11C.distance.components.bottom.jpg width=65%><br>
+<img src=./distance/img/D11C.distance.components.bottom.jpg width=45%><br>
 
-### [Thermistor/pressure input](./thermistor-or-pressure)
+### [ADC+10k input](./adc_10k)
 
-<img src=./thermistor-or-pressure/img/D11C.10k.ADC.components.jpg width=65%><br>
+<img src=./thermistor-or-pressure/img/D11C.10k.ADC.components.jpg width=45%><br>
 
 ### [Potentiometer input](./potentiometer)
 
-<img src=./potentiometer/img/D11C.potentiometer.components.top.jpg width=65%><br>
+<img src=./potentiometer/img/D11C.potentiometer.components.top.jpg width=45%><br>
 
-<img src=./potentiometer/img/D11C.potentiometer.components.bottom.jpg width=65%><br>
+<img src=./potentiometer/img/D11C.potentiometer.components.bottom.jpg width=45%><br>
 
 ## Outputs
 
 ### [MOSFET output](./mosfet)
 
-<img src=./mosfet/img/D11C.mosfet.components.jpg width=65%><br>
+<img src=./mosfet/img/D11C.mosfet.components.jpg width=45%><br>
 
 ### [Stepper output](https://gitlab.cba.mit.edu/neilg/urumbu/-/tree/master/serialstep)
 
-<img src=./extra/img/D11C.stepper.components.jpg width=65%><br>
+<img src=./extra/img/D11C.stepper.components.jpg width=45%><br>
 
 ### [Servo output](https://gitlab.cba.mit.edu/neilg/urumbu/-/tree/master/serialservo)
 
-<img src=./extra/img/D11C.servo.components.jpg width=65%><br>
+<img src=./extra/img/D11C.servo.components.jpg width=45%><br>
diff --git a/adc_10k/README.md b/adc_10k/README.md
new file mode 100644
index 0000000..bc50abf
--- /dev/null
+++ b/adc_10k/README.md
@@ -0,0 +1,32 @@
+# Urumbu capacitive input
+
+<img src=./img/D11C.ADC10k.components.jpg width=40%><br>
+
+This board returns a 10-bit value based on an ADC pin reading from a voltage divider between a 10k resistor and a variable resistor device the user can plug in. Examples include:
+
+- NTC 100k thermistor
+- Force sensor
+
+## Code
+
+The firmware can be found [here](./code/serialadc/serialadc.ino).
+
+## pcb.py file
+
+- [board](./hello.ADC10k-D11C)
+
+## .png files
+
+<img src=./img/hello.ADC10k-D11C.board.png width=30%><br>
+
+Traces:
+
+<img src=./img/hello.ADC10k-D11C.traces.png width=30%><br>
+
+Traces + exterior:
+
+<img src=./img/hello.ADC10k-D11C.traces_exterior.png width=30%><br>
+
+Interior:
+
+<img src=./img/hello.ADC10k-D11C.interior.png width=30%><br>
diff --git a/thermistor-or-pressure/code/d11_pressure/d11_pressure.ino b/adc_10k/code/serialadc/serialadc.ino
similarity index 69%
rename from thermistor-or-pressure/code/d11_pressure/d11_pressure.ino
rename to adc_10k/code/serialadc/serialadc.ino
index 764ab92..c10abd4 100644
--- a/thermistor-or-pressure/code/d11_pressure/d11_pressure.ino
+++ b/adc_10k/code/serialadc/serialadc.ino
@@ -1,9 +1,23 @@
+//
+// serialadc.ino
+//
+// serial 10-bit ADC
+//
+// Quentin Bolsee 11/29/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.
+//
+
 #define PIN_LED_A 4
 #define PIN_LED_C 2
 #define PIN_SENSOR 5
 
 
-#define VAL_MIN 2300
+#define VAL_MIN 0
 #define VAL_MAX 4095
 
 
diff --git a/adc_10k/hello.ADC10k-D11C b/adc_10k/hello.ADC10k-D11C
new file mode 100644
index 0000000..2b1e256
--- /dev/null
+++ b/adc_10k/hello.ADC10k-D11C
@@ -0,0 +1,8203 @@
+#!/usr/bin/env python3
+#
+# hello.NTC100k-D11C
+#    NTC 100k hello-world with D11C interface
+#
+# usage:
+#    hello.NTC100k-D11C | frep.py [dpi [filename]]
+#
+# Quentin Bolsee 6/29/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 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))
+
+
+class header_ntc(part):
+   #
+   # 2x1x0.1 ntc thermistor header
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      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,'THERM'))
+      #
+      # pin 2
+      #
+      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,'GND'))
+
+
+############################################################
+# define board
+############################################################
+
+width = 1.4 # board width
+height = .74 # board height
+x = 1 # x origin
+y = 1 # y origin
+zt = 0 # top z
+zb = -0.06 # bottom z
+w1 = .015 # thicker wire width
+w2 = .03 # thickest wire width
+mask = .004 # solder mask size
+
+pcb = PCB(x,y,width,height,mask)
+
+IC1 = SAMD11C('IC1\nD11C')
+pcb = IC1.add(pcb,x+width-.68,y+.45,angle=-90)
+
+J1 = header_SWD_4_1('J1\nSWD')
+pcb = J1.add(pcb,IC1.pad[7].x-.14,IC1.y,angle=-90)
+
+pcb = wire(pcb,w1,
+   J1.pad[1],
+   point(J1.pad[1].x,IC1.pad[7].y),
+   IC1.pad[7])
+
+pcb = wire(pcb,w1,
+   J1.pad[2],
+   point(J1.pad[2].x,IC1.pad[8].y),
+   IC1.pad[8])
+
+pcb = wire(pcb,w1,
+   J1.pad[3],
+   point(J1.pad[3].x,IC1.pad[6].y+.08),
+   point(IC1.pad[6].x,IC1.pad[6].y+.08),
+   IC1.pad[6])
+
+pcb = wire(pcb,w1,
+   J1.pad[4],
+   point(J1.pad[4].x,IC1.pad[12].y-.08),
+   point(IC1.pad[11].x,IC1.pad[11].y-.08),
+   IC1.pad[11])
+
+J2 = USB_A_plug('J2\nUSB')
+pcb = J2.add(pcb,x+width-.29,y+height/2,angle=0)
+
+pcb = wire(pcb,w1,
+   J2.pad[2],
+   point(J2.pad[2].x-.04,J2.pad[2].y),
+   point(J2.pad[2].x-.07,IC1.y+.015),
+   point(IC1.pad[9].x,IC1.y+.015),
+   IC1.pad[9])
+
+pcb = wire(pcb,w1,
+   J2.pad[3],
+   point(J2.pad[3].x-.09,J2.pad[3].y),
+   point(J2.pad[3].x-.09,IC1.y-.015),
+   point(IC1.pad[10].x,IC1.y-.015),
+   IC1.pad[10])
+
+pcb = wire(pcb,w1,
+   J2.pad[4],
+   point(J2.pad[4].x-.12,J2.pad[4].y),
+   point(J2.pad[4].x-.12,IC1.y-.045),
+   point(IC1.pad[11].x,IC1.y-.045),
+   IC1.pad[11])
+
+IC2 = regulator_SOT23('IC2\n3.3V')
+pcb = IC2.add(pcb,IC1.pad[5].x+0.02,IC1.pad[9].y-.18,angle=0)
+
+C1 = C_1206('C1\n1uF')
+pcb = C1.add(pcb,IC2.x-.18,IC2.y)
+
+pcb = wire(pcb,w1,
+   C1.pad[1],
+   point(C1.pad[1].x,C1.y+.07),
+   point(IC2.pad[1].x,C1.y+.07),
+   IC2.pad[1])
+
+pcb = wire(pcb,w1,
+   C1.pad[1],
+   point(C1.pad[1].x,C1.y+.07),
+   point(IC1.pad[12].x,C1.y+.07),
+   IC1.pad[12])
+
+pcb = wire(pcb,w1,
+   C1.pad[2],
+   IC2.pad[3])
+
+R1 = R_1206('R1\n1k')
+pcb = R1.add(pcb,IC1.pad[14].x-.04,IC2.y,angle=90)
+
+pcb = wire(pcb,w1,
+   R1.pad[2],
+   point(IC1.pad[13].x,R1.pad[2].y),
+   IC1.pad[13])
+
+LED = LED_1206('LED')
+pcb = LED.add(pcb,R1.x+.1,R1.y,angle=-90)
+
+pcb = wire(pcb,w1,
+   LED.pad[1],
+   point(LED.x,IC1.pad[14].y),
+   IC1.pad[14])
+
+pcb = wire(pcb,w1,
+   LED.pad[2],
+   R1.pad[1])
+
+J3 = header_ntc('J3\nNTC')
+pcb = J3.add(pcb,x+.23,y+height - 0.2)
+
+R2 = R_1206('R2\n4.7k')
+pcb = R2.add(pcb, C1.pad[0].x-0.22, C1.pad[0].y)
+
+C2 = C_1206('C2\n10uF')
+pcb = C2.add(pcb, J3.pad[0].x, J3.pad[0].y-0.2, angle=90)
+
+pcb = wire(pcb,w1,
+           C2.pad[2],
+           J3.pad[2])
+
+pcb = wire(pcb,w1,
+           R2.pad[2],
+           C1.pad[1])
+
+pcb = wire(pcb,w1,
+   J3.pad[1],
+   point(J3.pad[1].x-0.09, J3.pad[1].y),
+   point(J3.pad[1].x-0.09, C2.pad[1].y),
+   C2.pad[1]
+   )
+
+pcb = wire(pcb,w1,
+   R2.pad[1],
+   C2.pad[1])
+
+pcb = wire(pcb,w1,
+   C2.pad[2],
+   point(J1.pad[4].x, C2.pad[2].y),
+   J1.pad[4])
+
+pcb = wire(pcb,w1,
+   J3.pad[1],
+   point(J3.pad[1].x,IC1.pad[1].y+.11),
+   point(IC1.pad[1].x,IC1.pad[1].y+.11),
+   IC1.pad[1])
+
+pcb = wire(pcb,w1,
+   J2.pad[1],
+   point(J2.pad[4].x-.11,J2.pad[1].y),
+   point(J2.pad[4].x-.11,IC1.pad[1].y+.15),
+   point(J3.pad[2].x-.14,IC1.pad[1].y+.15),
+   point(J3.pad[2].x-.14,IC2.pad[2].y-.04),
+   point(IC2.pad[2].x,IC2.pad[2].y-.04),
+   IC2.pad[2])
+
+pcb = wire(pcb,w1,
+   J2.pad[4],
+   point(J2.pad[4].x-0.12,J2.pad[4].y),
+   point(J2.pad[4].x-0.12,y+.03),
+   point(IC2.pad[3].x,y+.03),
+   IC2.pad[3])
+
+############################################################
+# 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/thermistor-or-pressure/img/D11C.10k.ADC.components.jpg b/adc_10k/img/D11C.ADC10k.components.jpg
similarity index 100%
rename from thermistor-or-pressure/img/D11C.10k.ADC.components.jpg
rename to adc_10k/img/D11C.ADC10k.components.jpg
diff --git a/thermistor-or-pressure/img/D11C.pressure.components.bottom.jpg b/adc_10k/img/D11C.pressure.components.bottom.jpg
similarity index 100%
rename from thermistor-or-pressure/img/D11C.pressure.components.bottom.jpg
rename to adc_10k/img/D11C.pressure.components.bottom.jpg
diff --git a/thermistor-or-pressure/img/D11C.pressure.components.top.jpg b/adc_10k/img/D11C.pressure.components.top.jpg
similarity index 100%
rename from thermistor-or-pressure/img/D11C.pressure.components.top.jpg
rename to adc_10k/img/D11C.pressure.components.top.jpg
diff --git a/adc_10k/img/hello.ADC10k-D11C.board.png b/adc_10k/img/hello.ADC10k-D11C.board.png
new file mode 100644
index 0000000000000000000000000000000000000000..8b25626c9995734655d348dbce8caa4203d63b69
GIT binary patch
literal 22936
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
Mp00i_>zopr09BS^-v9sr

literal 0
HcmV?d00001

diff --git a/adc_10k/img/hello.ADC10k-D11C.interior.png b/adc_10k/img/hello.ADC10k-D11C.interior.png
new file mode 100644
index 0000000000000000000000000000000000000000..ab7215c870c2b9967deb92a06a8b91133aa9e505
GIT binary patch
literal 6883
zcmeAS@N?(olHy`uVBq!ia0y~yV7<-2!0gV!#=yXEZbr*;1_lPs0*}aI28NlZK$!9I
z#3f1$3{q1)T^vIy=DfLekoS;-0E?r3(LYUj%L^XeuAwZS^UlUxFV$lJfd|R!-!g(2
z3?E98ticSIQJTKt@cmmuzUA{Ae~_*JE}Y5nXL!I~v5gtTbx;|lN5g@EVKg0#(0ovm
z&ksuf6`P9BePd}jK6~a{&Y9_><uoWvM(e53bTFC@7#K$L!Dv1h%?G3TV6+?<EeA%+
zfzfhcv>X^M2ZmKS@ckReI}Pff&M(6shVx}0E<?wWp+h&6?=H(>X5cw&p!4_ti)S3X
zu8g0U&NneKFenJ!1`ofE(xc%3O4g(4fJ*7W%D6bb9~7bt4f88U=-}aCn>^SOxP)&C
T=ZTw#K=I<~>gTe~DWM4f9t(Ng

literal 0
HcmV?d00001

diff --git a/adc_10k/img/hello.ADC10k-D11C.traces.png b/adc_10k/img/hello.ADC10k-D11C.traces.png
new file mode 100644
index 0000000000000000000000000000000000000000..67c5cdf71e4b315c451449d3891bcce4bd7dce70
GIT binary patch
literal 8411
zcmeAS@N?(olHy`uVBq!ia0y~yV7<-2!0gV!#=yXEZbr*;1_lPs0*}aI28NlZK$!9I
z#3f1$3<?aME{-7;bKcyIo_5Pa%pq{m^k?=@U-avhhu-{Y*K{HIJ>!J%X^Ib@xJvaO
zPqt$Kfd={C=U*{`SPT!|94P}cI!5WyaA06yz?lxVU1cudD?WEsnSp_!z$m%rsxrfY
z(>=!@FI@CVZ=x&%LxWcd`vblhx3+T5w+svnZw@~9W_ah2^W66y2O|T+2KD*Ij61A0
z%7Oz~Y2#e`8)gg)3=br0?y)>LMXj_4a-%NTX$%Y>QoxQq@bE?sJIK-ok0DBDMB6eH
z*n&O7u;GS8@>dQ927T3S%)13|GBW&ldcE5DqAbG>?&%X5%M`aTGkg$xFU;7mTi|x%
z8Fmc@2D?Xpl^6=xldM5uz~GW(J>f<W6T<`TJ^3sQ>-?w`Bw#1TLjwMTFT|-blg`q)
zWZ8C=nc+bA8O!i~hBp~K8>?6t7#d<b-!jO|I>C4S%j=!GyO<dm!XFwLG0052z<2$5
zB_9JrOzRE41B#pl1@iOWGcX(w?Es}+1_l9;wm#kP9rEX^8K_uDf}J?;n8a%LhUnSF
z>*N?27!o*VBkTl463FfWp>tQWGu$(K9%Fmx^4yma$0b&~gPif;K+ZO15W_)*NP5d!
zIfjPUGm6*AC2p5ICb8S*T$a0qdi9P|KS4Qu7a`-Gu&rcZV5rIJpPl!=ipP8(8^gL2
zX`tjQe@l6b{pXJi41Erubo(IoJlEqUYlZ?-aN^FdDiaXD!`PrLcpF@`DHJt_<Q;v+
z!@y8;cJ)2$^OkoFL>YFlY@8b{a1*4UA-zaaQqMnwouT1<<=5(r_cs|Ev;}VOG|9gO
zmJSzynj>_3r%p6DiVmzsN*)Xhf9|i!@A#Fb#ZXXo8&sXXO9*w5N`CXJ;=E1YdAZ*{
z$3IQ9?SIU5{6mFBU)KA_3=9v_3Hcp8h(STw2TIE=$LAD-GCl*t0r8t4-!m}Ktw00i
zZiWNt&*p#=L<2v%{U=gW9xMQ*X;3O**awL$22fc87H|Pa4;A>}K(;eJ7GdiIN~KH;
z3=IA$n_)G|;HDSleq~@_C^tA3VS7k#U6D-xanru1kfgDA=cz&lhCQ=j#U&(-uz*WZ
z8#(^_0nul{$)5@#h$|*;zhZ3Ie%3O)|A2juVOT!{1H<$OoB0^RQ^^cnuy13IgX*e3
z$1E8c7#gl`xXA}j4HIvG=$h{Q^Na`PqtyEkZs%-gKCr(Nl+_OObG&2tU=D6B{McyN
z_JWV0|9En=Ey#$1x^ljE;Ls^xFoWk&P@ZK_5TY{wRv16n$~17@Mtl3v-4C|^z*bPy
zFfimxC9jcVY~ThJa1~q=Wg8a%{<_<%ggt>@PnntFz`K?*hI2>W>oR;(*v8DTLHi(6
zgYl=|+znnx#YKYoHYP?3<Ne1OG*H66VgHRh_6N&B)l<H7@*25^-lwE5ZkADIU?|Wp
z_M0Eh@WTwXmfBxvDao+U8_8$}hKlC5WeoeAQN`LpVp-srvytluCkcj_2@!k;Rzuol
zdfEN<&$zxZ)U<*V1_J{mfyB&uTgDLQh+>xB`7&#U^J?H)sAl2=z5~@@KRgiob|a6y
z;XAl&K9IX(4iCe5C9om}XqB}+X}4@cI-)!WCCJ+w@A4hE2Q~oK=zTCPXFKzT<=~uJ
zz?Q^ypsM;vAwz{2$mbs#Etg;5D-bwe;k)fF-+?%g#)|d|rUIY1`HU7ypoDr);R%Dx
z?Ro1jZ@bNSqZ!#Z`!~+zDB#<6o6$lDq>$l(;tu8uVCO<w8Vn2!^&sc?gVR1-?0>>;
z*@pQy!uT0%j!WLVvA5`$?L8e(ReYctQbznaR%Xp`Ulr=tCq_n~w3;uG{N!!P?Y9N8
zdV#0YLGHXUkw1~)zPbl<0V^n>Ffe@Jt9N02uo@%>Z}B(qgHnJts+d1W%otp191!Pt
z$57*f5+Og7Zog&N<BlrE1`=~c6;r$Ymf;U-WAg_iNbK^qDo~rC6kNCHIi#>P*n?`9
z2I(2aTyGEL?OFEcth^k<50G&U-NHv2(m(!UVyG9s&B*ZJP>aEXn|sbN9QY3l$(@c`
z1>D<m*PZ-o$Y}TMyZi^OV!!ui8Ftvte#<atnshO!h;Ucj##~U<1Zqxfn015ifGWp3
z1_p)$USK~$O4#X%yFqnH1jtebJk>0?T4X4&0T&J2J099F{FwtQ!%>0}mcAGmI_@Zl
z?qD^qtnO956Og@La^0u;XB^K{_`@yb85kI1rlV_*aRc@K6$(yTGsy9Sk|6^F!vxes
z0&c2;;(b7yjSM@QEuT-CZ++~>*N^imW#-#{i|l(k_4vkDHFKWE)Eq0^lY6z$M((#f
zH^TvKPy~a*^+cL=%#^hXAh%b@LOnOIo?u|G*lhXym0*LoMDiNB#^%i^bru7|#M37j
z7}}q&zRB>t;Mw)+>0%5F;Ed>C^4#XDJU2rFIEgpR<#@+X5D!jKZ#)Xv8>&%C^@Q|o
zw;3PQ;YuN(BA9`J;m?%UkC_WZh^^ni^~8snhR0qBZUXs$f$x3C`tNc385`DbLiYr6
z$;6;jdgS$2<^$y@iRwTRsI0OEmsJ)l2W1<KK{<}0;jlz<$2*2Om%y2pq2c~q%^l}K
zy{!X`kg}ZmO;S)E`yd0V>}5`YS`!Qm2V8&dVLb3yaT_zko+F`lE%8q+<odH^PNyFa
z`1j-Ase1Y27v-z{!z=O_7}h+1l!ybDML<2O2Ug%N(469*JmC-TgNpCC!^F1dZoguD
z&;c$RLAk{52(kLWX%AAGfiz-ifloI*7GVo&K{FHxBUDdM0~dV^6|5WQo)*3XDli+;
zg>Ua{1-HN$7#M8MZmVLbSZdAs9h}NQWw#kP3oyXyT1*<$pNr|5%?$FoHWd@fg931$
zV~6Sb!wd``Y7xF*Xir%!l)$@wKLf)DQ03LG`h#K5wCk}93_o^)D)$c);~%D<+gTyh
z@LK35Bf|pW+l&^hiX077!~S0^|9bxa-B<TdyZ`=PabEj*Os(I$cRK&o8()9^ouE5?
zA}B;~r}7iLK@S(jl{)tnDJz(Rnz0NIv<QU`dXEpr2lf0I7#J+}g9AE26IMXp%wca3
z-s}jf7mh1zV?Myy`35u~rvs|l)s?p}GcX+Z*zuO3K*<SI$H`1a%I)fjt3ef8A8M-&
zhj;WcAtNYxC{@1R@i1!!hV|Rl$}uo7B=|d7uPJ=~{2sV#D$@Y6D(28!XL$yO*PU+}
z3YeKh!h^Q4+ln(VG^7`z*KN28Kw`zA1?8NZ;BrBx0cJiZz&D(k^ZA4Q`E5!J3?D>^
zEkjXCX$H#s5}-2K<~k^B-d7#XN$y$xzbCY>CNKVJ#`Etdo*((V*80=W+Sb+c;~5wl
zP7%u4c@wx87(Q^CbJ~eLXJ)Waf+Yu7xxKT8hk@br4iOdxh61|z8013+28bW!!JQKZ
z1|xKr!CjbU&9J=mOSZt_sTKPe85nBL5b`rpj>b`nfrN=4X8?^KJXj7YG=5A6<*Emn
zecx&xSMRZ7WH|5{)+)g@N_>Jhh>_vJqq?Hz+eN{l=2uu59`u2d8Uvn^50;n7rNL!D
z!|z$e>*O8=gPWNQ4C)E6J~=p`=UW`!ZV;FG)!c4Qzx`S}bp}{IIDtPO{m8E_-*U^1
zhb7<&^Y8!r*Vwg8YPh`R+}5>gi_h);*zjS~E)Gd}Z`!JipTXwZnKyEc>>IZ|Pxg(Q
z{gsu0;eoavwC6#t|47wW@<xt<p<#Y@THe1iQLk6tXTKBwQ<j-w&QwszbHMjV5ko`v
zIs#=huJ|QY{KXCMV1)hoGc~_AXRo#PV`3<f2d7wb&4n@y4?=f>+wKeu;JzUP7P@}I
zso1q!%Rr+o3=AJis27;Usc9fn3(D^mGB7l_3*G)X<*Ww72d_Q185kJ)A^m3thmtpP
z4WED2GUcq@S}DZP@V;=7ECWM@*v7g0f9>!Ty~o(FS@;GcLxb#*vb?0vplL~lg0pkM
zl^Wspl<aQMl#9jgnKx~j<RkbQ9`wvX=@8<mbMSPwNR6I>Ru4%YAEK^B?RIBiXjopn
z2~_oBNd@3WHi_apjEr}?GyGGYC&>UB>H!r&;8>ks6eRjXe4Z%72RBe~|MPHR-uFn7
zk>UNbqMd8*Ix{dZJl{TTE%OJr6!wN}a9U+xaG_U*8R!@p*7h&^@_s%814AQdEx-Wg
aq8H+2iluyoy^51SHM6IypUXO@geCx-@e}v}

literal 0
HcmV?d00001

diff --git a/adc_10k/img/hello.ADC10k-D11C.traces_exterior.png b/adc_10k/img/hello.ADC10k-D11C.traces_exterior.png
new file mode 100644
index 0000000000000000000000000000000000000000..3fedc70ff4f226a667f47c30ce5ccba59453b3ac
GIT binary patch
literal 8448
zcmeAS@N?(olHy`uVBq!ia0y~yV7<-2!0gV!#=yXEZbr*;1_lPs0*}aI28NlZK$!9I
z#3f1$3<?aME{-7;bKcyIo_5Pa%pq{m^k?=@U-avhhu-{Y*K{HIJ>!J%X^Ib@xJnhD
z`^f+Xb#Lrfvx8X;n}u&Pf>;VdqcmN^;Z_*`hUtdKUI{WVFf>TdDqbhY*ucEuCLhQV
z3=?k*Zu;W3Du#23=XO@HFfcIqrS)vAVqvI|+&GuN^9=(7!=Eeb&rexo%~1Zp$Y_su
z20H^o0>526QvrLDb^a$e4hDt>+n;kd4_xhh3-+u)=i5IAw}DdO`3IlX7{b-IF@wY%
zR4Amktd(oXmP}qF$H>6YpgtQE!VG-J)2u;;Gq@xTQTp~P#)j83!JcV2dQ4)qI|D<7
z=0@2Yy(jn>4(RW{C*Adq;Xv$;9-a-{3uPG^wpYyOV7SwIgD=I-fsx^Z;Cpe#25SL$
zUT-`yO^AUZ{$Z^$LqRFEf&}Em-%{X!Z^#FyY=#FDawv>VQd7g0wQ>v$`;tIuG{HT&
z=c+OT1H&7y9QFqnT*`JVi$9-xQI>&W2iNq8j1M-nl<lxPU(CSpK<h{u1D|I@^Y0He
z><kR+9CE;=WP?Wz`-6g<ornHb++${7NLQzlSHMpEW^ydTmg&x|ImKT&7#JA5Zy@Xh
zB~*~z143s++cJFEX8HV;;JkM}$1OmP1i6DfZL=(hW>DIQgEseIWnf_704Gh0y&waO
zW<xXj%^dawbN3(GU*e2oQmtQdJWt^dx0GjKV2GK1whU})#}OR#9R*Pah6ew)g_qyP
z_dh&#o#BA!O;AWZaIS9omTo7<a6qsFWXqn{k%=({><sJNz_PyQ`5rY{GZd)8(stg2
zQ)_R`VPt4nUwO6qx#e={WlRjy6}A;~D}l>{4?cRzho5r3WnlPVyS|S9t*tdf0c(==
z^k=>hX)c&KN!HU-SA#>KLKHb98vaLr<qf>=!^&_jFWQ!Y;ehO#E|27%So!xekAJ+G
zJpW~c-KOV-F%Ko=_>Tv^t(9S5_|rqk@91H&?JDyD!Cu3#{tq+2<p2W%!w)4`7$XW*
zaDWQXik}N=LHsxaO|~Bt(e2;a!y|J=A{m^h84iepBa4B7>d6_DOc@TOgHqdxXLCTM
zA;W`CdY3h%mQ67A-~!+QAIR}Hj)wL<{<!1VMo7{qGzqulV`vE93~La8(?~-Cs5oml
z{`jGE)@oXXs0S$HFfcTLLKad0{Ah=?QyvJ_Tw{E&irmlz`L^M;MDiNB#`_lP3=9k(
zq|D$I5vY#N|M=FD;m2f@wolFMw`B}J%)wdghu}e3hJTRefxX!=fxC<kK33#_(jf!G
zx%cM|)`CKZf$spVtN7cmK#diKb2;F45AE$klsVum?E<!c2e@ozc;E}J+X@sxiu@Hf
zF&C8VuM6*d$MEK0Y6=6xjky>24$S<qm-T=gs1zwvjbJEntE*=WKrR;E91BxmNPqTS
zf}s^9>_3R#e#`LZ%C;(o2e}|yYCJ2ItEMHhFfhDJJ@@i67sGwj%HV;yo;ve^a%7_!
z81gsV<vUOgE}Iz`prz4!kXSgl1Zg<__#-GuFg9=too1{M1s5X+Qr~_&9&=ExVLhUy
z0!kp>oA2@+&_*%qz|)&~><?~&Jjc+WFLZ~oq95#sJBQ?Mzh(F!2TnLUc&AThd=Lp%
z#J~WlV;+R%Y-j$!0}3_<2557zz<S$l#v8N21~5Py;ddszEo1lwO1lgU=Nx<(Bl7z#
z_!!P7fvQ0}gXbc*82KJau0ILV*bUP7UcjHB@8oM^26s>{KOo&A(~x}obLp)zYldoM
z-#jqiCd_#5V3{?8yArrPVZ&0+AO&_V1GI8|pug=l;}1<#F?o=)g+WcM=N5;hcZZ+b
zaeQ_vC|y+aL&}KzH}cpY?1uR@#tqbee88LBvuAGJZrOE*RkMEffZS>QNs;HlZ<b7k
zbq7ERg@NJT!~PWvHB&)y3^31sV7&d7p$08gaDv3Z)hojfrh~E#{U{N_5TCMJw&6Rf
z*!_gvvJKnO#6arqqb3%6kh=O?Vf+jX413Oj>Xrkn9cLImsDqM40duk6LfIR=*Qf0N
zd6=1DKghU(!X}9iI&tv~5As1V88btG&1Uv>NroTtuuwDiV9h(Y?X2leJGBGH|NLW)
zOFj2;uO!3v^v$vjmy4417#J8HXdEeH@bfPKHTJ@UZ!_*-IS8uRBRrucA*lIhl(QYw
zD_IS)lmVWQVF?;RgA+AFUplC0NMJOd!`?6-UWTItEi8x`7$!<DVcPycEq{Gsi*(jo
z)5D?v&dWTU^X8$}b7lsHhS!^5RRB!;=@X#nX3?u;Kkzsalnfad7>r=v9VGOk+^-A_
z4CMyTV?Grhm)LE0&$$2b=Hqs!H}3gl5jMAf^PKMU7Jb{-TJ;@I{-4aqP@xKnU{JW;
z%xUl5Bns+QGOSOAdJbn(lg6Hfc!Gf;-RyacEz<`kP#IWIfKq2MFensBN-{k7P-80n
zK<?b1s`r<e7#hGCvE$jC<^Pfy87_d6_y*yFvJCIMK`E+1mh&A$fj=m{!b_evXUeP@
z?m&tzq?7@Ta!_|0G)yqRsJ4co?+~%|8@QgZGd>n!>jd_}frqjmzutRo&hQ}=-4iII
zKMhO!D)!bf{Ln)Q--vT%*08=$yTT6Uf;6xX3M7(wF3L6pLozMHhuy}k-$9Lj1`7sQ
zoPq-YPo5!F9+b!CC7;__)#428-tW+uZ_ZF*bEJ%+Vfv0!?H^Xl9DiKcoBZ>Q#3}jv
z@ju@`w)mC&{w3FWUWNuyNQnq5W9d(WQ&r4yiR9_WXBO+tf2j4Rnt_4gKsK=*KTx|&
z<|3$U1Qi1ZI*HW>YuDkXpKk)SL_wx9<T-&-Dg&s!{`?Z8=wn!~u&ubV3DOVBNwVH<
z0BV7OlI8N7Vf+m1OO`*d1LYHt{yS~pEC8!(vCwxEL>s&dixU_a7!p{im{4TSf%_cW
zpOs25FzoY(`-1(!gq%>OH4ndvGceS-<*+~4z#`vp{nIXP1_t}>prHc0PuhRZSc>~I
z6~uzNf+b1T49gW*7&lycW&dm4zn}Y~|5pFZ_%HXq^68w_=TF|9`}Ds`L2aG<nx{ra
zARi-Y0QA(n(@`tt%Idt1z&w^G%Ru!CLrg27(1F$7==8R$ph}40xj8tXby8sk<m|T$
z1xaS0df|b@kunAg#fcz``i`ciFg!?U0d=V@KrJCZ7tml_Lo!lsf1r}Hm6?IzKq0!b
zvGEV6f_j|{3<r9VtHA?LZ)CAEJh%#R+#An~cGGu%?tsVJ8kj*%o(At7#V?o{5^Oih
zGUPclJn}mAZNYOU28Ith>(J{qXn{xW_$REOG?oU9J|T^#f&zTn%woBJ&u@mYFfi;R
zx(o%Eaj^Cw6=-n74Kyb9Fn0Zn+@6nL=5IVT@%-D>GH?IL{hU*=uhiXc|N4TjpSc+r
z0tof+PVfdXGBDUZR6BV5Q4IrwdkQQ$z{>6E6B!v2B&RnqFfgp6n~%Y@PQ!DsADux}
zCIf>5YCi#~%)Oq&{$NXA9dFVOq4VYp3=RE+{EWNw0=3>i<rQf(s5E8x10JaOZv@I!
zHfJx+%dhFbuFk+vVMnN7+Ucmpzz}oCKd&G<Z`G@|T?`C&CW4Y01C|mGJuj2X2WPW_
z_~LU{m20v<%}fS{2Q08YIXDSC5KjLgc1(Nizhmv6KQ6!eoP_~4uP_trxP}AUbr~vb
zV0s`OY6kFl`+@q~yBAMAw$Pwwk<5wT`#-%us-PSq`#P`M=xx;Zqx?+^Z^{ILYXwLs
zpWt6|XmWJ++j$4(?%4MH@hltj>*5Ry4eu?eoUaL$2NySj>d^JsYfHbTr#)L(&%a~u
zr+OZSf-rFQ4HrDk$e>r*%L6W`X+H9Q{2gd`V9&g**Vfxx8=J>4F%(Ec+@ZNphT%aZ
zL5I{SOr1Sz=3Qa1bLGyR1eM=ZNl<!gwwC!bFzm3rU&z4FP%U)(=alw9h6gi$<S{ca
z+=2CbL4o=FYaLTgnwdT$!w*^YTZ{}1?t-^}F7M}GdB~cfpp40yfnh`QjdP(kdze6u
zjQMnqNH_M~1yx|@^44yxW|H3_$8bQ>lFmtmP*S3`JScP-7(T?LrF~~%V5qQAM;-!W
zV4!Fowt+i)?Oox9{~gtA4A2^S0;nE8uzXGkYu%x}Obq|P^|5|u#)0xX$_x+ICw~X^
zfA8E&zI7%ij%iNo2|kADpn~av`w>$Hh99%8gW41fkg|bc2+$>O<O;NnH&=s`C4>Gc
z>g63!I)@G&Q6(=@*Ss?ijxS<hU|0rP3jm5gT2?@mntzXBc1?@SL*9gEpfK=s^>bP0
Hl+XkK%+nt2

literal 0
HcmV?d00001

diff --git a/capacitive/README.md b/capacitive/README.md
index 0a43835..e6bb9ea 100644
--- a/capacitive/README.md
+++ b/capacitive/README.md
@@ -1,12 +1,12 @@
 # Urumbu capacitive input
 
-![](./img/D11C.capacitive.components.top.jpg)
+<img src=./img/D11C.capacitive.components.top.jpg width=40%><br>
 
 This board returns a 10-bit value depending on the capacitive sensing pad reading.
 
 ## Code
 
-Code can be found [here](./code/d11_capa/d11_capa.ino).
+The firmware can be found [here](./code/d11_capa/d11_capa.ino).
 
 ## KiCad files
 
@@ -16,10 +16,16 @@ Code can be found [here](./code/d11_capa/d11_capa.ino).
 
 ## .png files
 
-![](./img/samd11c14_capa-composite.png)
+<img src=./img/samd11c14_capa-composite.png width=30%><br>
 
-![](./img/samd11c14_capa-F_Cu.png)
+Traces:
 
-![](./img/samd11c14_capa-Edge_Cuts.png)
+<img src=./img/samd11c14_capa-F_Cu.png width=30%><br>
 
-![](./img/samd11c14_capa-interior_traces_comp.png)
+Interior:
+
+<img src=./img/samd11c14_capa-Edge_Cuts.png width=30%><br>
+
+Traces + exterior:
+
+<img src=./img/samd11c14_capa-interior_traces_comp.png width=30%><br>
diff --git a/capacitive/code/d11_capa/d11_capa.ino b/capacitive/code/serialcapa/serialcapa.ino
similarity index 74%
rename from capacitive/code/d11_capa/d11_capa.ino
rename to capacitive/code/serialcapa/serialcapa.ino
index ab0b9e4..b9ff49b 100644
--- a/capacitive/code/d11_capa/d11_capa.ino
+++ b/capacitive/code/serialcapa/serialcapa.ino
@@ -1,3 +1,17 @@
+//
+// serialcapa.ino
+//
+// serial capacitive sensing
+//
+// Quentin Bolsee 11/29/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.
+//
+
 #include "Adafruit_FreeTouch.h"
 
 #define PIN_LED_A 4
@@ -15,7 +29,6 @@ Adafruit_FreeTouch qt(PIN_CAPA, OVERSAMPLE_4, RESISTOR_50K, FREQ_MODE_NONE);
 
 
 void setup() {
-  // put your setup code here, to run once:
   pinMode(PIN_LED_A, OUTPUT);
   digitalWrite(PIN_LED_A, HIGH);
   pinMode(PIN_LED_C, OUTPUT);
diff --git a/distance/README.md b/distance/README.md
index 6f21da8..5b4f6f4 100644
--- a/distance/README.md
+++ b/distance/README.md
@@ -8,7 +8,7 @@ This board returns a 10-bit value depending on the distance read by the HC-SR04
 
 ## Code
 
-Code can be found [here](./code/d11_distance/d11_distance.ino).
+The firmware can be found [here](./code/d11_distance/d11_distance.ino).
 
 ## KiCad files
 
diff --git a/distance/code/d11_distance/d11_distance.ino b/distance/code/serial_hcsr04/serial_hcsr04.ino
similarity index 77%
rename from distance/code/d11_distance/d11_distance.ino
rename to distance/code/serial_hcsr04/serial_hcsr04.ino
index 4742d0e..e92e8c9 100644
--- a/distance/code/d11_distance/d11_distance.ino
+++ b/distance/code/serial_hcsr04/serial_hcsr04.ino
@@ -1,3 +1,17 @@
+//
+// serial_hcsr04.ino
+//
+// serial HC SR04
+//
+// Quentin Bolsee 11/29/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.
+//
+
 #define PIN_LED_A 4
 #define PIN_LED_C 2
 
@@ -12,7 +26,6 @@
 
 
 void setup() {
-  // put your setup code here, to run once:
   pinMode(PIN_LED_A, OUTPUT);
   digitalWrite(PIN_LED_A, HIGH);
   pinMode(PIN_LED_C, OUTPUT);
@@ -20,7 +33,6 @@ void setup() {
   pinMode(PIN_TRIG, OUTPUT);
   pinMode(PIN_ECHO, INPUT);
   SerialUSB.begin(115200);
-
 }
 
 
diff --git a/mosfet/README.md b/mosfet/README.md
index 305705c..2360e97 100644
--- a/mosfet/README.md
+++ b/mosfet/README.md
@@ -1,5 +1,29 @@
-# Urumbu MOSFET output
+# Urumbu capacitive input
 
-![](./img/D11C.mosfet.components.jpg)
+<img src=./img/D11C.mosfet.components.jpg width=40%><br>
 
-This board lets you control an external device through a MOSFET. An external power supply feeds the current to the load.
+This board returns a 10-bit value depending on the capacitive sensing pad reading.
+
+## Code
+
+The firmware can be found [here](./code/serialnmos/serialnmos.ino).
+
+## pcb.py file
+
+- [board](./hello.NMOS-D11C)
+
+## .png files
+
+<img src=./img/hello.NMOS-D11C.board.png width=30%><br>
+
+Traces:
+
+<img src=./img/hello.NMOS-D11C.traces.png width=30%><br>
+
+Traces + exterior:
+
+<img src=./img/hello.NMOS-D11C.traces_exterior.png width=30%><br>
+
+Interior:
+
+<img src=./img/hello.NMOS-D11C.interior.png width=30%><br>
diff --git a/mosfet/code/serialnmos/serialnmos.ino b/mosfet/code/serialnmos/serialnmos.ino
new file mode 100644
index 0000000..8170315
--- /dev/null
+++ b/mosfet/code/serialnmos/serialnmos.ino
@@ -0,0 +1,41 @@
+//
+// serialnmos.ino
+//
+// serial NMOS gate
+//
+// Quentin Bolsee 11/29/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.
+//
+
+#define PIN_LED_A 4
+#define PIN_LED_C 2
+#define PIN_GATE 5
+
+void setup() {
+  // put your setup code here, to run once:
+  pinMode(PIN_LED_A, OUTPUT);
+  digitalWrite(PIN_LED_A, HIGH);
+  pinMode(PIN_LED_C, OUTPUT);
+  digitalWrite(PIN_LED_C, LOW);
+  pinMode(PIN_GATE, OUTPUT);
+  digitalWrite(PIN_GATE, LOW);
+  SerialUSB.begin(115200);
+}
+
+void loop() {
+  if (SerialUSB.available()) {
+    char c = SerialUSB.read();
+    if (c == '1') {
+      digitalWrite(PIN_GATE, HIGH);
+    } else if (c == '0') {
+      digitalWrite(PIN_GATE, LOW);
+    } else if (c == '@') {
+      SerialUSB.write("0007");
+    }
+  }
+}
diff --git a/mosfet/hello.NMOS-D11C b/mosfet/hello.NMOS-D11C
new file mode 100644
index 0000000..5cf13d0
--- /dev/null
+++ b/mosfet/hello.NMOS-D11C
@@ -0,0 +1,8255 @@
+#!/usr/bin/env python3
+#
+# hello.NMOS-D11C
+#    NMOS hello-world with D11C interface
+#
+# usage:
+#    hello.NMOS-D11C | frep.py [dpi [filename]]
+#
+# Quentin Bolsee 6/29/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_out(part):
+   #
+   # 2x1x0.1 ptc power OUTPUT header
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      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,'+'))
+      #
+      # pin 2
+      #
+      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,'-'))
+
+
+class header_power_in(part):
+   #
+   # 2x1x0.1 ptc power OUTPUT header
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      #
+      # pin 1
+      #
+      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,'VCC'))
+      #
+      # pin 2
+      #
+      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,'GND'))
+
+
+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.45 # board width
+height = 1.05 # board height
+x = 1 # x origin
+y = 1 # y origin
+zt = 0 # top z
+zb = -0.06 # bottom z
+w1 = .015 # thicker wire width
+w2 = .03 # thickest wire width
+mask = .004 # solder mask size
+
+pcb = PCB(x,y,width,height,mask)
+
+IC1 = SAMD11C('IC1\nD11C')
+pcb = IC1.add(pcb,x+width-.68,y+.45,angle=-90)
+
+J1 = header_SWD_4_1('J1\nSWD')
+pcb = J1.add(pcb,IC1.pad[7].x-.14,IC1.y,angle=-90)
+
+pcb = wire(pcb,w1,
+   J1.pad[1],
+   point(J1.pad[1].x,IC1.pad[7].y),
+   IC1.pad[7])
+
+pcb = wire(pcb,w1,
+   J1.pad[2],
+   point(J1.pad[2].x,IC1.pad[8].y),
+   IC1.pad[8])
+
+pcb = wire(pcb,w1,
+   J1.pad[3],
+   point(J1.pad[3].x,IC1.pad[6].y+.08),
+   point(IC1.pad[6].x,IC1.pad[6].y+.08),
+   IC1.pad[6])
+
+pcb = wire(pcb,w1,
+   J1.pad[4],
+   point(J1.pad[4].x,IC1.pad[12].y-.08),
+   point(IC1.pad[11].x,IC1.pad[11].y-.08),
+   IC1.pad[11])
+
+J2 = USB_A_plug('J2\nUSB')
+pcb = J2.add(pcb,x+width-.29,y+height/2,angle=0)
+
+pcb = wire(pcb,w1,
+   J2.pad[2],
+   point(J2.pad[2].x-.07,J2.pad[2].y),
+   point(J2.pad[2].x-.15,IC1.y+.015),
+   point(IC1.pad[9].x,IC1.y+.015),
+   IC1.pad[9])
+
+pcb = wire(pcb,w1,
+   J2.pad[3],
+   point(J2.pad[3].x-.09,J2.pad[3].y),
+   point(J2.pad[3].x-.13,IC1.y-.015),
+   point(IC1.pad[10].x,IC1.y-.015),
+   IC1.pad[10])
+
+pcb = wire(pcb,w1,
+   J2.pad[4],
+   point(J2.pad[4].x-.12,J2.pad[4].y),
+   point(J2.pad[4].x-.12,IC1.y-.045),
+   point(IC1.pad[11].x,IC1.y-.045),
+   IC1.pad[11])
+
+IC2 = regulator_SOT23('IC2\n3.3V')
+pcb = IC2.add(pcb,IC1.pad[5].x+0.02,IC1.pad[9].y-.18,angle=0)
+
+C1 = C_1206('C1\n1uF')
+pcb = C1.add(pcb,IC2.x-.18,IC2.y)
+
+pcb = wire(pcb,w1,
+   C1.pad[1],
+   point(C1.pad[1].x,C1.y+.07),
+   point(IC2.pad[1].x,C1.y+.07),
+   IC2.pad[1])
+
+pcb = wire(pcb,w1,
+   C1.pad[1],
+   point(C1.pad[1].x,C1.y+.07),
+   point(IC1.pad[12].x,C1.y+.07),
+   IC1.pad[12])
+
+pcb = wire(pcb,w1,
+   C1.pad[2],
+   IC2.pad[3])
+
+R1 = R_1206('R1\n1k')
+pcb = R1.add(pcb,IC1.pad[14].x-.04,IC2.y,angle=90)
+
+pcb = wire(pcb,w1,
+   R1.pad[2],
+   point(IC1.pad[13].x,R1.pad[2].y),
+   IC1.pad[13])
+
+LED = LED_1206('LED')
+pcb = LED.add(pcb,R1.x+.1,R1.y,angle=-90)
+
+pcb = wire(pcb,w1,
+   LED.pad[1],
+   point(LED.x,IC1.pad[14].y),
+   IC1.pad[14])
+
+pcb = wire(pcb,w1,
+   LED.pad[2],
+   R1.pad[1])
+
+J3 = header_power_out('J3\nOUT')
+pcb = J3.add(pcb,x+.24,J1.pad[0].y+0.45)
+
+J4 = header_power_in('J4\nIN')
+pcb = J4.add(pcb,x+.24,C1.pad[0].y)
+
+IC3 = NMOSFET_TO252AA('IC3\nNMOS')
+pcb = IC3.add(pcb,x+0.75,IC1.pad[0].y+0.39, angle=90)
+
+R2 = C_1206('R2\n10k')
+pcb = R2.add(pcb,IC3.pad[0].x+0.12,IC3.pad[0].y, angle=90)
+
+pcb = wire(pcb,w1,
+   IC3.pad[1],
+   point(R2.pad[1].x, IC3.pad[1].y),
+   R2.pad[1])
+
+pcb = wire(pcb,w1,
+   IC3.pad[2],
+   point(R2.pad[2].x, IC3.pad[2].y),
+   R2.pad[2])
+
+pcb = wire(pcb,w1,
+   IC3.pad[1],
+   point(IC1.pad[5].x, IC3.pad[1].y),
+   IC1.pad[5])
+
+pcb = wire(pcb,w1,
+   IC3.pad[2],
+   point(IC3.pad[2].x-0.09, IC3.pad[2].y),
+   point(IC3.pad[2].x-0.09, IC3.pad[1].y-0.07),
+   point(J1.pad[4].x-0.05, IC3.pad[1].y-0.07),
+   point(J1.pad[4].x-0.05, J1.pad[4].y),
+   J1.pad[4])
+
+pcb = wire(pcb,w1,
+   J4.pad[2],
+   point(J1.pad[4].x, J4.pad[2].y),
+   J1.pad[4])
+
+pcb = wire(pcb,w1,
+   J3.pad[2],
+   point(IC3.pad[3].x, J3.pad[2].y),
+   IC3.pad[3])
+
+C3 = C_FND('C2\n100uF')
+pcb = C3.add(pcb,J4.pad[0].x,J4.pad[0].y+0.28)
+
+C4 = C_1206('C4\n1uF')
+pcb = C4.add(pcb,J4.pad[0].x,C3.pad[1].y+0.13)
+
+pcb = wire(pcb,w1,
+   C3.pad[2],
+   point(C3.pad[2].x, J1.pad[4].y),
+   J1.pad[4])
+
+pcb = wire(pcb,w1,
+   C3.pad[1],
+   point(C3.pad[1].x-0.1, C3.pad[1].y))
+
+pcb = wire(pcb,w1,
+   C4.pad[2],
+   point(C4.pad[2].x+0.075, C4.pad[2].y))
+
+pcb = wire(pcb,w1,
+   J3.pad[1],
+   point(J3.pad[1].x-0.1, J3.pad[1].y),
+   point(J3.pad[1].x-0.1, J4.pad[1].y),
+   J4.pad[1])
+
+pcb = wire(pcb,w1,
+   J2.pad[1],
+   point(J2.pad[4].x-.11,J2.pad[1].y),
+   point(J2.pad[4].x-.11,IC1.pad[1].y+.45),
+   point(J3.pad[2].x-.15,IC1.pad[1].y+.45),
+   point(J3.pad[2].x-.15,IC2.pad[2].y-.09),
+   point(IC2.pad[2].x,IC2.pad[2].y-.09),
+   IC2.pad[2])
+
+pcb = wire(pcb,w1,
+   J2.pad[4],
+   point(J2.pad[4].x-0.12,J2.pad[4].y),
+   point(J2.pad[4].x-0.12,y+.03),
+   point(IC2.pad[3].x,y+.03),
+   IC2.pad[3])
+
+############################################################
+# 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/mosfet/img/hello.NMOS-D11C.board.png b/mosfet/img/hello.NMOS-D11C.board.png
new file mode 100644
index 0000000000000000000000000000000000000000..3b7fef08636371564277e3973793083752209d5d
GIT binary patch
literal 28854
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
E0OXBdL;wH)

literal 0
HcmV?d00001

diff --git a/mosfet/img/hello.NMOS-D11C.interior.png b/mosfet/img/hello.NMOS-D11C.interior.png
new file mode 100644
index 0000000000000000000000000000000000000000..33f11f54ebf46ef4d12ce29729e7103fdfb684bd
GIT binary patch
literal 9526
zcmeAS@N?(olHy`uVBq!ia0y~yVB=+AV5#L`V_;xNHD-Uyz`(#+;1OBOz%cU^2s1vO
zxI~G8L4m>3#WAE}&YRl@eOVkCm=DU8{9L}LX3jyyvy7pFKkk28IgbGZ8tUJ_{sv+&
zFg!5s02#`_;Gil65mAQHQ!^m^9w;5Mh!HGc0Hp&uAsP>i8o)q$7_7g|TzBfT&31KA
znEvs4KIgVD!w-RZkRTn6i_!E5N*AN)U^E?!ri0Nkk@V_iw2o#NZKp5{=`i@Z%NA7j
zHSC`Ee5Wnr1AmL>cjkRC^JfMLGAt0{1=9_JP}<7`%x7?e(pncGd<iJM!Udu+0ZNY=
zz%Uw!45MKH$|a+DVKg0#rUOX*Fq#)e^TG(s3k~nTy}i-KsL+u(L+->sZS~&r9U@Oy
z-m!u*#po!+=qLmzON^$2(R47H4u<|{RLweeP&5|2-dk?V*kJ!K6U1X+7@gl44Fgb0
z7)=MG>0mS+fI?u1rUSd;x_=A|EO$U_0U+KOox*2e7!8BbFaYHSqSHa>`d@MVARP=0
k?<z;v#4rq=bwQzj8M2lOGF*zgzYr8Zp00i_>zopr02H78pa1{>

literal 0
HcmV?d00001

diff --git a/mosfet/img/hello.NMOS-D11C.traces.png b/mosfet/img/hello.NMOS-D11C.traces.png
new file mode 100644
index 0000000000000000000000000000000000000000..b931bf425a3cefced4d40c08195946f81c1f0786
GIT binary patch
literal 11788
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
A6aWAK

literal 0
HcmV?d00001

diff --git a/mosfet/img/hello.NMOS-D11C.traces_exterior.png b/mosfet/img/hello.NMOS-D11C.traces_exterior.png
new file mode 100644
index 0000000000000000000000000000000000000000..5cd7161dc8072dfaad6fbf198a7ce33e8a794e81
GIT binary patch
literal 11846
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
UBHurLwE%^`r>mdKI;Vst03CmD#sB~S

literal 0
HcmV?d00001

diff --git a/potentiometer/README.md b/potentiometer/README.md
index e9d40be..c9db680 100644
--- a/potentiometer/README.md
+++ b/potentiometer/README.md
@@ -8,7 +8,7 @@ This board returns a 10-bit value depending on the potentiometer.
 
 ## Code
 
-Code can be found [here](./code/d11_pot/d11_pot.ino).
+The firmware be found [here](./code/d11_pot/d11_pot.ino).
 
 ## KiCad files
 
diff --git a/potentiometer/code/d11_pot/d11_pot.ino b/potentiometer/code/serialpot/serialpot.ino
similarity index 62%
rename from potentiometer/code/d11_pot/d11_pot.ino
rename to potentiometer/code/serialpot/serialpot.ino
index fffa0cd..a878a4e 100644
--- a/potentiometer/code/d11_pot/d11_pot.ino
+++ b/potentiometer/code/serialpot/serialpot.ino
@@ -1,10 +1,23 @@
+//
+// serailpot.ino
+//
+// serial potentiometer sensor
+//
+// Quentin Bolsee 11/29/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.
+//
+
 #define PIN_LED_A 4
 #define PIN_LED_C 2
 #define PIN_SENSOR 14
 
 
 void setup() {
-  // put your setup code here, to run once:
   pinMode(PIN_LED_A, OUTPUT);
   digitalWrite(PIN_LED_A, HIGH);
   pinMode(PIN_LED_C, OUTPUT);
@@ -13,11 +26,13 @@ void setup() {
   SerialUSB.begin(115200);
 }
 
+
 void print_16bit(int v) {
   const char bfr[] = {v & 0xFF, (v >> 8) & 0xFF};
   SerialUSB.write(bfr, 2);
 }
 
+
 void loop() {
   if (SerialUSB.available()) {
     char c = SerialUSB.read();
diff --git a/thermistor-or-pressure/README.md b/thermistor-or-pressure/README.md
deleted file mode 100644
index a765945..0000000
--- a/thermistor-or-pressure/README.md
+++ /dev/null
@@ -1,17 +0,0 @@
-# Urumbu thermistor/pressure input
-
-Bare:
-
-![](./img/D11C.10k.ADC.components.jpg)
-
-Pressure:
-
-![](./img/D11C.pressure.components.top.jpg)
-
-![](./img/D11C.pressure.components.bottom.jpg)
-
-This board returns a 10-bit value depending on the reading of the ADC, which is connected between a 10k resistor and a variable resistance device. This could be a 100k NTC or a pressure sensor.
-
-## Code
-
-Code can be found [here](./code/d11_pressure/d11_pressure.ino).
-- 
GitLab