示例#1
0
def set_first_pos(ref, row_num, row, ox, oy, ref_num, first_num):
    module = pcb.FindModuleByReference(ref + str(ref_num))
    x = (1 + row[0]) / 2 * PITCH + ox
    y = float(row_num) * PITCH + oy
    if ref == "D":
        y += 1.27 * 3
    module.SetPosition(pcbnew.wxPointMM(x, y))
    if ref == "D":
        module.SetOrientation(0 * 10)
#        module.Flip(pcbnew.wxPointMM(x,y))
    return x
示例#2
0
def set_first_pos(ref,row_num,row,ox,oy,ref_num,first_num):
    module=pcb.FindModuleByReference(ref+str(ref_num))
    x=(1+row[0])/2*PITCH+ox
    if ref=="D":
        x+=PITCH/2-1.27
    y=float(row_num)*PITCH+oy
    module.SetPosition(pcbnew.wxPointMM(x,y))    
    if ref=="D":
        module.SetOrientation(90*10)
    print "\n"
    return x
示例#3
0
 def Run(self):
     fn = self.get_sch_filename()
     positions = self.get_component_positions(fn)
     pcb = pcbnew.GetBoard()
     components = pcb.GetModules()
     for c in components:
         ref = c.GetReference()
         if ref in positions:
             x, y = int(positions[ref]['posx']) * 25.4 / 1000, int(
                 positions[ref]['posy']) * 25.4 / 1000
             c.SetPosition(pcbnew.wxPointMM(x, y))
示例#4
0
def calcpos(name):
    num = int(name.replace('D', '')) - 1

    row = math.floor(num / 8)

    if row % 2 == 0:
        x = ((num % 8) * 4) + 2
    else:
        x = (((7 % 8) * 4)) - ((num % 8) * 4) + 2
    y = (math.floor(num / 8) * 4) + 2
    return pcbnew.wxPointMM(x, y)
示例#5
0
def Layout():
    board = pcbnew.GetBoard()
    fname = path.join(path.dirname(board.GetFileName()), "layout.tsv")
    with open(fname) as f:
        r = csv.reader(f, delimiter='\t')
        data = [row for row in r]
    for d in data:
        m = board.FindModuleByReference(d[0])
        if m is not None:
            p = pcbnew.wxPointMM(float(d[1]), float(d[2]))
            m.SetPosition(p)
    pcbnew.Refresh()
示例#6
0
def arrangeInMatrix(moduleList, start, space, size, priority = HORIZON_THEN_VERTICAL):
    i,j = 0,0
    for index, module in enumerate(moduleList):
        if priority == HORIZON_THEN_VERTICAL:
            j = int( index%size )
            i = int( index/size )
        elif priority == VERTICAL_THEN_HORIZON:
            j = int( index/size )
            i = int( index%size )
        posx = start[0] + j*space[0]
        posy = start[1] + i*space[1]
        module.SetPosition(pcbnew.wxPointMM(posx,posy))
示例#7
0
def createTracks(x, y, wire_width=1000000):
    pcb = pcbnew.GetBoard()

    #get layer table
    layertable = {}
    numlayers = pcbnew.LAYER_ID_COUNT
    for i in range(numlayers):
        layertable[i] = pcb.GetLayerName(i)
        print("{} {}".format(i, pcb.GetLayerName(i)))

    # create tracks
    for lay in [0, 31]:
        for i in range(len(x)):
            t = pcbnew.TRACK(pcb)
            t.SetStart(pcbnew.wxPointMM(round(x[i - 1], 2), round(y[i - 1],
                                                                  2)))
            t.SetEnd(pcbnew.wxPointMM(round(x[i], 2), round(y[i], 2)))
            t.SetWidth(int(wire_width))
            t.SetLayer(lay)
            pcb.Add(t)
            print('Wire Generation Done!')
示例#8
0
 def npth(self, diameter, x, y):
     """put a npth in pcb with given diameter and location"""
     module = pcbnew.FOOTPRINT(self.pcb)
     npth = pcbnew.PAD(module)
     npth.SetAttribute(pcbnew.PAD_ATTRIB_NPTH)
     npth.SetShape(pcbnew.PAD_SHAPE_CIRCLE)
     npth.SetSize(pcbnew.wxSizeMM(diameter, diameter))
     npth.SetDrillShape(pcbnew.PAD_DRILL_SHAPE_CIRCLE)
     npth.SetDrillSize(pcbnew.wxSizeMM(diameter, diameter))
     module.Add(npth)
     self.pcb.Add(module)
     loc = pcbnew.wxPointMM(x, y)
     module.SetPosition(loc)
示例#9
0
def set_pos(ref, row_num, row, ox, oy, ref_num, first_num, prev):
    module = pcb.FindModuleByReference(ref + str(ref_num))
    col_num = ref_num - first_num
    x = (row[col_num - 1] + row[col_num]) / 2 * PITCH + prev
    y = float(row_num) * PITCH + oy
    if ref == "D":
        y += 1.27 * 3


#        module.Flip(pcbnew.wxPointMM(x,y))
    module.SetPosition(pcbnew.wxPointMM(x, y))
    if ref == "D":
        module.SetOrientation(0 * 10)
    return x
示例#10
0
def MoveRotateModuleToCirclePosition(index, module):
	
	adjustedCircleRadius = CircleRadius - ModuleSize / 2 - ModulePadding
	
	# calculate the new position and orientation of the module around the defined circle
	newModuleAngle 			= 360 / ModuleCount * ( index )	# the angle around the circle
	newModuleX 				= CircleCenterX - adjustedCircleRadius * math.cos( newModuleAngle * RADIANS_IN_DEGREE)
	newModuleY 				= CircleCenterY - adjustedCircleRadius * math.sin( newModuleAngle * RADIANS_IN_DEGREE)
	newModuleOrientation 	= (360 - (newModuleAngle + ModuleRotation)) * 10 # the rotation of the module
	
	# set the module's position and orientation it its new home around the defined circle
	module.SetPosition(pcbnew.wxPointMM(newModuleX, newModuleY))
	module.SetOrientation(newModuleOrientation)
	
	return
示例#11
0
def main():
    brd = pcbnew.GetBoard()
    m = brd.GetModules()

    while m is not None:
        print(m.GetReference())
        if m.GetReference()[0] == "D":
            _id = int(m.GetReference()[1:])
            theta = (360.0/32.0)*(_id - 1);
            thetar = math.radians(theta)
            x = xoff - 45.0 * math.sin(thetar)
            y = yoff - 45.0 * math.cos(thetar)
            m.SetPosition(pcbnew.wxPointMM(x, y))
            m.SetOrientation((theta+90.0)*10.0)
        m = m.Next()

    pcbnew.Refresh()
示例#12
0
def arrange_diodes():
    for i in range(1, 46 + 1):
        r = "SW" + str(i)
        sw = FindModuleByReference("SW" + str(i))
        d = FindModuleByReference("D" + str(i))
        angle = sw.GetOrientationDegrees()
        tmp_pos = pcbnew.ToMM(sw.GetPosition())
        sw_pos = MyPosition(tmp_pos[0], tmp_pos[1])
        d_pos = sw_pos + SwitchPosition(0, 0, -angle).up(-0.3).to_mm()
        d.SetPosition(pcbnew.wxPointMM(d_pos.x, d_pos.y))
        d.SetOrientationDegrees(angle)
        # ref position (relative from switch position)
        ref = d.Reference()
        ref.SetTextAngle(0)
        ref_pos_mm = (4.1, 0) if len(str(i)) == 1 else (4.6, 0)
        ref_pos = pcbnew.wxPoint(pcbnew.FromMM(ref_pos_mm[0]),
                                 pcbnew.FromMM(ref_pos_mm[1]))
        ref.SetPos0(ref_pos)
示例#13
0
def separate(input, output, source, page, debug, keepannotations):
    """
    Separate a single board out of a multi-board design. The separated board is
    placed in the middle of the sheet.

    You can specify the board via bounding box or annotation. See documentation
    for further details on usage.
    """
    try:
        from kikit import panelize_ui_impl as ki
        from kikit.panelize import Panel
        from pcbnewTransition.transition import isV6, pcbnew
        from pcbnew import LoadBoard, wxPointMM
        from kikit.common import fakeKiCADGui
        app = fakeKiCADGui()

        preset = ki.obtainPreset([], validate=False, source=source, page=page, debug=debug)

        if preset["debug"]["deterministic"] and isV6():
            pcbnew.KIID.SeedGenerator(42)

        board = LoadBoard(input)
        sourceArea = ki.readSourceArea(preset["source"], board)

        panel = Panel(output)
        panel.inheritDesignSettings(board)
        panel.inheritProperties(board)
        panel.inheritTitleBlock(board)

        destination = wxPointMM(150, 100)
        panel.appendBoard(input, destination, sourceArea,
            interpretAnnotations=(not keepannotations))
        ki.setStackup(preset["source"], panel)
        ki.positionPanel(preset["page"], panel)
        ki.setPageSize(preset["page"], panel, board)

        panel.save(reconstructArcs=True)
    except Exception as e:
        import sys
        sys.stderr.write("An error occurred: " + str(e) + "\n")
        sys.stderr.write("No output files produced\n")
        if isinstance(preset, dict) and preset["debug"]["trace"]:
            traceback.print_exc(file=sys.stderr)
        sys.exit(1)
示例#14
0
def set_matrix_position(ref_prefix, matrix):
    i = 0
    for yi, rows in enumerate(matrix):
        for xi, p in enumerate(rows):
            i += 1
            ref = "%s%s" % (ref_prefix, i)
            xp = xi * PITCH + p[0]
            yp = yi * PITCH + p[1]
            orientation = p[2]
            set_position(ref, xp, yp, orientation)

    xp = xi * PITCH + p[0]
    yp = yi * PITCH + p[1]
    orientation = p[2]
    set_position(ref, xp, yp, orientation)

    module = pcb.FindModuleByReference(ref)
    module.SetPosition(pcbnew.wxPointMM(xp + OFFSET_X, yp + OFFSET_Y))
    module.SetOrientation(orientation * 10.0)
示例#15
0
def MoveRotateModuleToCirclePosition(index, module):

    adjustedCircleRadius = CircleRadius - ModuleSize / 2 - ModulePadding

    # calculate the new position and orientation of the module around the defined circle
    newModuleAngle = 360 / ModuleCount * (index)  # the angle around the circle
    newModuleX = CircleCenterX - adjustedCircleRadius * math.cos(
        newModuleAngle * RADIANS_IN_DEGREE)
    newModuleY = CircleCenterY - adjustedCircleRadius * math.sin(
        newModuleAngle * RADIANS_IN_DEGREE)
    newModuleOrientation = (
        360 -
        (newModuleAngle + ModuleRotation)) * 10  # the rotation of the module

    # set the module's position and orientation it its new home around the defined circle
    module.SetPosition(pcbnew.wxPointMM(newModuleX, newModuleY))
    module.SetOrientation(newModuleOrientation)

    return
示例#16
0
def change_silk_position(board, parts_head, parts_num_range, silk_moment,
                         angle):
    ps, pf = parts_num_range
    mx, my = silk_moment

    print("---------------------------")
    print("get Parts reference")
    D = [
        board.FindModuleByReference(parts_head + str(i))
        for i in range(ps, pf + 1)
    ]

    print("change silk position")
    for d in D:
        dpos = d.GetPosition()
        dx = dpos[0] / 1000000.0
        dy = dpos[1] / 1000000.0
        ref = d.Reference()
        ref.SetPosition(pcbnew.wxPointMM(dx + mx, dy + my))
        ref.SetTextAngle(angle * 10)
示例#17
0
def arrange_in_matrix(board, parts_head, parts_num_range, matrix_size,
                      grid_moment, offset, angle):
    msx, msy = matrix_size
    gmx, gmy = grid_moment
    ox, oy = offset
    ps, pf = parts_num_range

    print("---------------------------")
    print("get Parts reference")
    D = [
        board.FindModuleByReference(parts_head + str(i))
        for i in range(ps, pf + 1)
    ]

    print("display Parts in N*N matrix")
    for iy in range(msy):
        for ix in range(msx):
            num = iy * msx + ix
            D[num].SetPosition(pcbnew.wxPointMM(ox + ix * gmx, oy + iy * gmy))
            D[num].SetOrientation(angle * 10.0)
示例#18
0
def arrange_leds(center):
    led_corresponds = {
        "LED1": "LED14",
        "LED2": "LED13",
        "LED3": "LED12",
        "LED4": "LED11",
        "LED5": "LED10",
        "LED6": "LED9",
        "LED7": "LED8",
    }
    led_positions = {
        "LED1": MyPosition(148.45, 33.80),
        "LED2": MyPosition(114.10, 32.10),
        "LED3": MyPosition(65.00, 43.30),
        "LED4": MyPosition(34.30, 91.30),
        "LED5": MyPosition(75.95, 95.05),
        "LED6": MyPosition(110.25, 109.95),
        "LED7": MyPosition(147.40, 126.00)
    }

    for ref, pos in led_positions.items():
        led = FindModuleByReference(ref)
        led.SetPosition(pcbnew.wxPointMM(pos.x, pos.y))
    move_right_modules_left_mirror(center, led_corresponds)
示例#19
0
import pcbnew
import csv

reader = csv.reader(open("positions.csv"), delimiter=";")
data = {}
n = 0
for row in reader:
    n += 1
    key = row[0]
    data[key] = row[1:]

pcb = pcbnew.LoadBoard("Clavier.kicad_pcb")
for i in range(1, n + 1):
    c = pcb.FindModuleByReference("K" + str(i))
    c.SetPosition(
        pcbnew.wxPointMM(float(data["K" + str(i)][0]),
                         -float(data["K" + str(i)][1])))
    d = pcb.FindModuleByReference("D" + str(i))
    d.SetPosition(
        pcbnew.wxPointMM(float(data["K" + str(i)][2]),
                         -float(data["K" + str(i)][3])))

pcb.Save("Clavier.kicad_pcb")
示例#20
0
            1: 3.1614 * 20,
            2: 3.1614 * 00,
            3: 3.1614 * -20,
            4: 3.1614 * -60,
            5: 3.1614 * 60,
            6: 0,
        }
        y += 4
        rotation = rotate.get(digits / 5)
        module.SetOrientation(0)
    else:
        rotation = 0
        module.SetOrientation(0)

    if letters in ('SF', 'DD'):
        module.SetPosition(pcbnew.wxPointMM(x - xoffset, y - yoffset))
        print letters, x, y

    if letters in ('DB'):
        module.SetPosition(pcbnew.wxPointMM(x - xoffset - 1, y - yoffset + 4))
        print letters, x, y

    if letters in ('-DB', '-DD'):
        module.SetOrientation(1800)
        module.SetPosition(
            pcbnew.wxPointMM(0 - 200 - xoffset, 0 - 200 - yoffset))

    if letters == 'D':
        module.SetPosition(pcbnew.wxPointMM(x - xoffset, y - yoffset))

S15 = b.FindModuleByReference('SF20')
示例#21
0
        cnt += 1
        x, y, r = sw_coord(i, j + cs[i], "0", i, j + cs[i], "1", "1", og)
        sw_pos["SW{}".format(cnt)] = (float(x), float(y), float(r))
# define thumb cluster
for t in (t1, t2, t3, t4):
    cnt += 1
    x, y, r = sw_coord(*t, origin=og)
    sw_pos["SW{}".format(cnt)] = (float(x), float(y), float(r))

## RHS
## define top three rows
#for j, cn in enumerate(columns):
#    for i in range(cn):
#        cnt += 1
#        x, y, r = sw_coord(7-i, j+cs[i], "0", 7-i, j+cs[i], "1", "1", og_r)
#        sw_pos["K{}".format(cnt)] = (float(x), float(y), float(r))
## define thumb cluster
#for t in (t1, t2, t3, t4):
#    cnt += 1
#    x, y, r = sw_coord(*t, origin=og_r, fliplr=True)
#    sw_pos["K{}".format(cnt)] = (float(x), float(y), float(r))

# set switch position
import pcbnew
board = pcbnew.GetBoard()
for key in sw_pos:
    sw = board.FindModuleByReference(key)
    print key, sw_pos[key]
    sw.SetPosition(pcbnew.wxPointMM(sw_pos[key][0], sw_pos[key][1]))
    sw.SetOrientation(sw_pos[key][2])
示例#22
0
    def BuildThisFootprint(self):

        dial_params = self.parameters['Dial']
        dial_angle = dial_params['*angle']
        dial_offset_angle = dial_params['*offset angle']
        dial_radius = dial_params['radius']
        dial_inner_arc = dial_params['*inner arc']
        dial_outer_arc = dial_params['*outer arc']
        
        tick_params = self.parameters ['Ticks']
        tick_show = tick_params['*show ticks']
        tick_num_divisions = tick_params['*number of divisions']
        tick_length = tick_params['tick length']

        label_params = self.parameters ['Labels']
        label_show = label_params['*show labels']
        label_min = label_params['*min']
        label_step = label_params['*step']

        text_size = self.GetTextSize()  # IPC nominal
        thickness = self.GetTextThickness()
        # self.draw.GetLineTickness())
        textposy = self.GetTextSize()
         
        self.draw.Value( 0, textposy, text_size )
        self.draw.Reference( 0, -textposy, text_size )

        layer = pcbnew.F_SilkS
        center = pcbnew.wxPointMM(0,0)

        # inner arc
        if dial_inner_arc:
            start = pcbnew.wxPoint (center.x, center.y - dial_radius)
            start = rotate_about (center, start, dial_angle/2.0+ dial_offset_angle)

            self.draw.SetLayer(layer)
            self.draw.SetLineTickness(pcbnew.FromMM (0.15))
            self.draw.Arc (center.x, center.y, start.x, start.y, dial_angle*10)

        # outer arc
        if dial_outer_arc:
            start = pcbnew.wxPoint (center.x, center.y - dial_radius - tick_length)
            start = rotate_about (center, start, dial_angle/2.0+ dial_offset_angle)
            self.draw.SetLayer(layer)
            self.draw.SetLineTickness(pcbnew.FromMM (0.15))
            self.draw.Arc (center.x, center.y, start.x, start.y, dial_angle*10)

        # center cross
        self.draw.SetLayer(layer)
        self.draw.SetLineTickness(pcbnew.FromMM (0.15))
        start = pcbnew.wxPointMM(-2, 0)
        end = pcbnew.wxPointMM(2, 0)
        self.draw.Line (start.x, start.y, end.x, end.y)
        start = pcbnew.wxPointMM(0, -2)
        end = pcbnew.wxPointMM(0, 2)
        self.draw.Line (start.x, start.y, end.x, end.y)

        for j in range (0, tick_num_divisions+1):
            ang = j * dial_angle/tick_num_divisions - dial_angle/2.0 - dial_offset_angle
            ang = -ang

            start = pcbnew.wxPoint (center.x, center.y - dial_radius)
            end = pcbnew.wxPoint (center.x, center.y - dial_radius - tick_length)

            start = rotate_about (center, start, ang)
            end = rotate_about (center, end, ang)

            #
            if tick_show:
                self.draw.SetLayer(layer)
                self.draw.SetLineTickness(pcbnew.FromMM (0.15))
                self.draw.Line (start.x, start.y, end.x, end.y)

            if label_show and j * dial_angle/tick_num_divisions < 360:
                text_pos = pcbnew.wxPoint (center.x, center.y - dial_radius - tick_length - text_size*1.25)
                text_pos = rotate_about (center, text_pos, ang)

                #
                text = pcbnew.TEXTE_MODULE(self.module)

                text.SetPosition (text_pos)
                #text.SetOrientation (ang*10.0)
                text.SetThickness (pcbnew.FromMM (0.15))
                text.SetLayer(layer)
                text.SetText (str(label_min + j*label_step))

                self.module.Add (text)
示例#23
0
def set_footprint_position(name, xp, yp, rot):
    module = pcb.FindModuleByReference(name)
    module.SetPosition(pcbnew.wxPointMM(xp + OFFSET_X, yp + OFFSET_Y))
    module.SetOrientationDegrees(rot)
示例#24
0
 def MoveToMM(self, x, y):
     self.MoveTo(pcbnew.wxPointMM(x, y))
示例#25
0
def _point_mm(x, y):
    """Convert coordinate in mm to internal coordinate"""
    return pcbnew.wxPointMM(float(x), float(y))
示例#26
0
def set_hole_pos_by_sw(pcb, sw_name):
    sw = pcb.FindModuleByReference(sw_name)
    sw_x, sw_y = pcbnew.ToMM(sw.GetPosition())
    hole_name = "HOLE" + str(sw_name.replace("SW", ""))
    hole_obj = pcb.FindModuleByReference(hole_name)
    hole_obj.SetPosition(pcbnew.wxPointMM(sw_x + HOLE_PITCH, sw_y + HOLE_PITCH))
示例#27
0
def _point_mm(x, y):
    """Convert coordinate in mm to internal coordinate"""
    return pcbnew.wxPointMM(float(x), float(y))
示例#28
0
def move_left_switches_origin():
    for r in switch_refs["left"]:
        m = FindModuleByReference(r)
        print("ref:", m.GetReference(), ", pos:", m.GetPosition())
        m.SetPosition(pcbnew.wxPointMM(0, 0))
        m.SetOrientationDegrees(0)
示例#29
0
from kikit import panelize
import pcbnew
import sys

####################### CONSTANTS AND VARIABLES ####################################################

#board dimensions
altezzaScheda = 28  # board height
lunghezzaScheda = 43  # board length

# coordinates of panel origin
# NOTE: in pcbnew, Y increases going DOWN
panelOriginX = 15
panelOriginY = 19
panelOrigin = pcbnew.wxPointMM(panelOriginX, panelOriginY)

# panel configuration
righe = 5  #rows
colonne = 4  #columns
spazioOrizzontale = 8  # horizontal space between boards
spazioVerticale = 0  # vertical space between boards
diametroFresa = 2  # milling tool diameter
spessoreBinari = 6  # rails thickness

# in my case, i had to create a "high tab" and "low tab"
# in order to leave space for the WiFi module antenna
# those tabs then "merge" in the junction area of the boards
spessoreTabAlta = 5  #high tab thickness
spessoreTabBassa = 2  #low tab thickness
offsetVerticaleTabBassa = altezzaScheda - spessoreTabBassa  #vertical offset of low tab
示例#30
0
def set_position(ref, xp, yp, orientation=0):
    module = pcb.FindModuleByReference(ref)
    module.SetPosition(pcbnew.wxPointMM(xp + OFFSET_X, yp + OFFSET_Y))
    module.SetOrientation(orientation * 10.0)
'C6':[5640, 209.882705254665, 60.8048210421939], 
'C5':[5760, 206.234646149846, 54.4862300687321], 
'C4':[5880, 201.352596469568, 49.0641900429244], 
'C3':[6000, 195.449925393752, 44.7756703341086], 
'C2':[6120, 188.784608192886, 41.8080999922281], 
};



for aModule in pcb.GetModules():
	modRef = aModule.GetReference();
	print('Module Ref: ' + modRef)
	try:
		modNewData = modulePositions[modRef]
		print(' Module Found.')
		aModule.SetPosition(pcbnew.wxPointMM(float(modNewData[1]), float(modNewData[2])))
		aModule.SetOrientation(modNewData[0])
		print(' Module moved.')
	except KeyError:
		print(' Module Not Found!')
			

		
		
		
		
		
		
		
		
		
示例#32
0
 def make_point(p):
     x, y = p
     return pcbnew.wxPointMM(x, y)
示例#33
0
def arrange_left():
    P = MyPosition
    SP = SwitchPosition
    # base_pos: SW14
    base_pos = P(52.8, 51.575)
    sw_pos_u = {
        # col 1
        "SW1": SP(0, 0, 0),
        "SW7": SP(0, 1, 0),
        "SW14": SP(0, 2, 0),
        # col0
        "SW6": SP(-1, 0.75, 0),
        "SW13": SP(-1, 1.75, 0)
    }

    # col2
    col2_orientation = 6
    sw_pos_u["SW15"] = sw_pos_u["SW14"].right(0.5).up(0.1).change_angle(
        col2_orientation).right(0.5).up(0.5)
    sw_pos_u["SW8"] = sw_pos_u["SW15"].up(1)
    sw_pos_u["SW2"] = sw_pos_u["SW8"].up(1)

    # col3
    col3_orientation = 10
    sw_pos_u["SW16"] = sw_pos_u["SW15"].right(0.5).change_angle(
        col3_orientation).right(0.5).up(0.5)
    sw_pos_u["SW9"] = sw_pos_u["SW16"].up(1)
    sw_pos_u["SW3"] = sw_pos_u["SW9"].up(1)

    # col4
    sw_pos_u["SW4"] = sw_pos_u["SW3"].right(1).up(-0.25)
    sw_pos_u["SW10"] = sw_pos_u["SW4"].up(-1)
    sw_pos_u["SW17"] = sw_pos_u["SW10"].up(-1)

    # col5
    sw_pos_u["SW5"] = sw_pos_u["SW4"].right(1).up(-0.125)
    sw_pos_u["SW11"] = sw_pos_u["SW5"].up(-1)
    sw_pos_u["SW18"] = sw_pos_u["SW11"].up(-1)

    # col6
    sw_pos_u["SW12"] = sw_pos_u["SW11"].right(1).up(-0.125)
    sw_pos_u["SW19"] = sw_pos_u["SW12"].up(-1)

    # thumb
    sw_pos_u["SW21"] = sw_pos_u["SW18"].right(-0.5).up(-0.5).change_angle(
        18).right(0.5).up(-0.5)
    sw_pos_u["SW20"] = sw_pos_u["SW21"].right(-0.5).up(-0.5).change_angle(
        10).right(-0.5).up(0.5)
    sw_pos_u["SW22"] = sw_pos_u["SW21"].right(0.5).up(-0.5).change_angle(
        26).right(0.5).up(0.5)
    sw_pos_u["SW23"] = sw_pos_u["SW21"].up(-1)

    # u -> mm
    sw_pos_mm = {r: v.to_mm() + base_pos for r, v in sw_pos_u.items()}
    # # dbg: print
    # for r in sorted(sw_pos_mm.keys()):
    #     print("{}: {}".format(r, sw_pos_mm[r]))

    # move
    for r, pos in sw_pos_mm.items():
        m = FindModuleByReference(r)
        m.SetPosition(pcbnew.wxPointMM(pos.x, pos.y))
        m.SetOrientationDegrees(-pos.angle_deg)