diff --git a/python/pcb.py b/python/pcb.py
index 98518a996068301b33f338ad6452a6e83c5caef0..13bdc6d5e1dced5af6e26dd13e274b41843d7513 100755
--- a/python/pcb.py
+++ b/python/pcb.py
@@ -6724,6 +6724,177 @@ class PicoW(part):
          self.pad.append(point(board_width/2+pad_offset,(0.5+i)*pad_pitch))
          self.labels.append(self.text(self.pad[-1].x-label_offset,self.pad[-1].y,self.pad[-1].z,str(31+i)))
 
+class XIAO_ESP32S3(part):
+   #
+   # XIAO ESP32S3
+   #
+   def __init__(self,value=''):
+      self.value = value
+      self.pad = [point(0,0,0)]
+      self.labels = []
+      padl = cube(-0.03,0.081,-0.070/2,0.070/2,0,0)
+      padr = cube(-0.081,0.03,-0.070/2,0.070/2,0,0)
+      pitch = 0.1
+      dx = 0.035
+      width = 0.685
+      length = 0.798
+      d = 0.015
+      l = 0.004 # text
+      #
+      # pin 1
+      #
+      self.shape = translate(padl,-width/2,3*pitch,0)
+      self.pad.append(point(-width/2,3*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x+dx,self.pad[-1].y,self.pad[-1].z,'D0'))
+      #
+      # pin 2
+      #
+      self.shape = add(self.shape,translate(padl,-width/2,2*pitch,0))
+      self.pad.append(point(-width/2,2*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x+dx,self.pad[-1].y,self.pad[-1].z,'D1'))
+      #
+      # pin 3
+      #
+      self.shape = add(self.shape,translate(padl,-width/2,1*pitch,0))
+      self.pad.append(point(-width/2,1*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x+dx,self.pad[-1].y,self.pad[-1].z,'D2'))
+      #
+      # pin 4
+      #
+      self.shape = add(self.shape,translate(padl,-width/2,0*pitch,0))
+      self.pad.append(point(-width/2,0*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x+dx,self.pad[-1].y,self.pad[-1].z,'D3'))
+      #
+      # pin 5
+      #
+      self.shape = add(self.shape,translate(padl,-width/2,-1*pitch,0))
+      self.pad.append(point(-width/2,-1*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x+dx,self.pad[-1].y,self.pad[-1].z,'SDA'))
+      #
+      # pin 6
+      #
+      self.shape = add(self.shape,translate(padl,-width/2,-2*pitch,0))
+      self.pad.append(point(-width/2,-2*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x+dx,self.pad[-1].y,self.pad[-1].z,'SCL'))
+      #
+      # pin 7
+      #
+      self.shape = add(self.shape,translate(padl,-width/2,-3*pitch,0))
+      self.pad.append(point(-width/2,-3*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x+dx,self.pad[-1].y,self.pad[-1].z,'TX'))
+      #
+      # pin 8
+      #
+      self.shape = add(self.shape,translate(padr,width/2,-3*pitch,0))
+      self.pad.append(point(width/2,-3*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x-dx,self.pad[-1].y,self.pad[-1].z,'RX'))
+      #
+      # pin 9
+      #
+      self.shape = add(self.shape,translate(padr,width/2,-2*pitch,0))
+      self.pad.append(point(width/2,-2*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x-dx,self.pad[-1].y,self.pad[-1].z,'SCK'))
+      #
+      # pin 10
+      #
+      self.shape = add(self.shape,translate(padr,width/2,-1*pitch,0))
+      self.pad.append(point(width/2,-1*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x-dx,self.pad[-1].y,self.pad[-1].z,'SDI'))
+      #
+      # pin 11
+      #
+      self.shape = add(self.shape,translate(padr,width/2,0*pitch,0))
+      self.pad.append(point(width/2,0*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x-dx,self.pad[-1].y,self.pad[-1].z,'SDO'))
+      #
+      # pin 12
+      #
+      self.shape = add(self.shape,translate(padr,width/2,1*pitch,0))
+      self.pad.append(point(width/2,1*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x-dx,self.pad[-1].y,self.pad[-1].z,'3V3'))
+      #
+      # pin 13
+      #
+      self.shape = add(self.shape,translate(padr,width/2,2*pitch,0))
+      self.pad.append(point(width/2,2*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x-dx,self.pad[-1].y,self.pad[-1].z,'G'))
+      #
+      # pin 14
+      #
+      self.shape = add(self.shape,translate(padr,width/2,3*pitch,0))
+      self.pad.append(point(width/2,3*pitch,0))
+      self.labels.append(self.text(self.pad[-1].x-dx,self.pad[-1].y,self.pad[-1].z,'5V'))
+      #
+      # JTAG
+      #
+      dw = 0.052
+      left = 0.297
+      right = 0.399
+      top = 0.064
+      dy = 0.099
+      pad = cube(-dw/2,dw/2,-dw/2,dw/2,0,0)
+      #
+      self.shape = add(self.shape,translate(pad,-width/2+left,length/2-top,0))
+      self.pad.append(point(-width/2+left,length/2-top))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'MTDI',line=l))
+      #
+      self.shape = add(self.shape,translate(pad,-width/2+right,length/2-top,0))
+      self.pad.append(point(-width/2+right,length/2-top))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'MTDO',line=l))
+      #
+      self.shape = add(self.shape,translate(pad,-width/2+left,length/2-top-dy,0))
+      self.pad.append(point(-width/2+left,length/2-top-dy))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'EN',line=l))
+      #
+      self.shape = add(self.shape,translate(pad,-width/2+right,length/2-top-dy,0))
+      self.pad.append(point(-width/2+right,length/2-top-dy))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',line=l))
+      #
+      self.shape = add(self.shape,translate(pad,-width/2+left,length/2-top-2*dy,0))
+      self.pad.append(point(-width/2+left,length/2-top-2*dy))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'MTMS',line=l))
+      #
+      self.shape = add(self.shape,translate(pad,-width/2+right,length/2-top-2*dy,0))
+      self.pad.append(point(-width/2+right,length/2-top-2*dy))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'MTCK',line=l))
+      #
+      self.shape = add(self.shape,translate(pad,-width/2+left,length/2-top-3*dy,0))
+      self.pad.append(point(-width/2+left,length/2-top-3*dy))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'D-',line=l))
+      #
+      self.shape = add(self.shape,translate(pad,-width/2+right,length/2-top-3*dy,0))
+      self.pad.append(point(-width/2+right,length/2-top-3*dy))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'D+',line=l))
+      #
+      # battery
+      #
+      dx = 0.084
+      dy = 0.045
+      left = 0.124
+      topm = 0.283
+      topp = 0.359
+      pad = cube(-dx/2,dx/2,-dy/2,dy/2,0,0)
+      #
+      self.shape = add(self.shape,translate(pad,-width/2+left+dx/2,length/2-topm-dy/2,0))
+      self.pad.append(point(-width/2+left+dx/2,length/2-topm-dy/2))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'-'))
+      #
+      self.shape = add(self.shape,translate(pad,-width/2+left+dx/2,length/2-topp-dy/2,0))
+      self.pad.append(point(-width/2+left+dx/2,length/2-topp-dy/2))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'+'))
+      #
+      # thermal
+      #
+      left = 0.333
+      top = 0.429
+      dx = 0.108
+      dy = 0.100
+      pad = cube(-dx/2,dx/2,-dy/2,dy/2,0,0)
+      #
+      self.shape = add(self.shape,translate(pad,-width/2+left+dx/2,length/2-top-dy/2,0))
+      self.pad.append(point(-width/2+left+dx/2,length/2-top-dy/2))
+      self.labels.append(self.text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'thermal',line=l))
+
 class XIAO_ESP32C3(part):
    #
    # XIAO ESP32C3