diff --git a/python/pcb.py b/python/pcb.py
index 4fd97ca97aaa2d0bc21ba23b88682cdbd29f7833..95ca24190b4957038ccf331b1158ae49224651f5 100755
--- a/python/pcb.py
+++ b/python/pcb.py
@@ -2454,6 +2454,248 @@ class HM11(part):
       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
@@ -2564,9 +2806,6 @@ class ESP32_CAM(part):
       self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'3V3'))
 
 
-pad_ESP8266 = cube(-.0493,.0493,-.0197,.0197,0,0)
-pad_ESP8266_bot = cube(-.0197,.0197,-.0415,.0415,0,0)
-
 class ESP8266_12E(part):
    #
    # ESP8266 12E
@@ -2582,6 +2821,8 @@ class ESP8266_12E(part):
       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:
       #
@@ -3692,9 +3933,6 @@ class regulator_SOT23(part):
       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'))
 
-pad_SOT223 = cube(-.02,.02,-.03,.03,0,0)
-pad_SOT223_ground = cube(-.065,.065,-.03,.03,0,0)
-
 class regulator_SOT223(part):
    #
    # Zetex ZLDO1117
@@ -3706,6 +3944,8 @@ class regulator_SOT223(part):
       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
       #