Skip to content

bert/pscad

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

28 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

OpenSCAD-like PCB footprint generator

http://www.openscad.org
http://pcb.geda-project.org/

This python library allows PCB footprints to be generated via a syntax that is
similar to the OpenSCAD syntax. The library does not actually parse input,
instead the footprint is made up of calls to the library which look similar
to OpenSCAD calls with the '+' taking the place of contiuation, and the ','
taking the place of ';'. For instance:

OpenSCAD:
scale(5)
square([1, 4]);

translate([5, 3, 0])
circle(1);

pscad:
scale(5) +
square([1, 4]),

translate([5, 3]) +
circle(1)

At the base of pscad is the ability to build simply shapes and apply
affine transformation matrixes to them. The supported shapes are:

circle(r, [sweep])
donut(r1, r2)
square(v, [center], [rounded])
line(v, [center])
point()
polygon(v, points, [paths])

The supported transformations are:

multmatrix(m)
translate(v)
rotate(angle)
scale(v)
mirror(normal)

The points can then be assigned various object types:

silk(w)
pad(name, clearance, mask)
pin(name, clearance, mask)
bore(clearance, mask)
mark()
text()

The assignment will be carried out on every applicable child object type
similarly to the OpenSCAD 'color' command. 'pad' only works with 'square' and
'circle', 'bore' only works with 'circle', and 'donut' only works with 'pin'.
There is also 'back' which puts pads on the opposite side of the board and a
'nopaste' that keeps the paste stencil closed.

The 'name' parameter to 'pad' and 'pin' can be a simple string or an iterable.
Each time another pad is placed, 'next()' is called on the iterable. To allow
pads composed of multiple pieces, the 'union' command causes all children
to take the same pad name.

The 'element' command takes a pscad tree and outputs a PCB element to stdout.

The helper 'up', 'down', 'left', 'right' are wrappers to transform.

'rounded_square' produces a square with rounded edges (only works with 'pad').

'row(obj, pitch, n, [center])' repeats 'obj' 'n' times with a spacing of 'pitch'
in the positive x direction.

The pscad.py library can be executed as a script in order to load a '.pscad'
component for processing. Usage will be shown in the example below

Example BGA component:

# module bga
#
# Copyright (C) 2012 Russ Dill <Russ.Dill@asu.edu>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.

import pscad
from decimal import Decimal as D
from string import ascii_uppercase
import itertools
import re
import patterns

defaults = {
    'clearance' :   "0.15",
    'mask' :        "0.05",
    'silk' :        "0.2",
    'no_letter' :   "IOQSYZ",
    'placement' :   "1",
    'grid' :        "0.1",
    'invert' :      "False"
}

def bga_letters(skip):
    return itertools.ifilterfalse(lambda x: x in skip, ascii_uppercase)

def bga_dletters(skip):
    return (i[0] + i[1] for i in itertools.product([''] + list(bga_letters(skip)), bga_letters(skip)))

def bga_names(n, skip):
    return (i[0] + str(i[1]) for i in itertools.product(bga_dletters(skip), range(1, n+1)))

def part(m):
    m = pscad.wrapper(defaults.items() + m.items())

    if 'skip' in m:
        skip = lambda name: re.match(m.skip, name)
    else:
        skip = None

    row = pscad.row(pscad.circle(m.pad_size / D(2)), m.pitch, m.n_x, center=True)
    all = (
        pscad.pad(bga_names(m.n_x, m.no_letter), m.clearance, m.mask, skip=skip) +
        pscad.rotate(270) + pscad.row(pscad.rotate(90) + row, m.pitch, m.n_y, center=True),

        pscad.silk(m.silk) + pscad.square((m.body_x, m.body_y), center=True)
    )

    silk = pscad.silk(m.silk) + (
        patterns.placement_courtyard(all, m.placement, m.grid, 1),

        pscad.translate([-m.body_x / D(2), -m.pitch * (m.n_y - 1) / D(2)]) +
        pscad.left(m.silk * D(2)) + pscad.line([0, m.pitch * D(2)], center=True)
    )

    if m.invert:
        return pscad.mirror([1, 0]) + pscad.rotate(270) + (all, silk)

    return all, silk

And a .pscad file to go with it:

module bga

name		FF784
pad_size	0.45
pitch		1.0
n_x		28
n_y		28
body_x		29
body_y		29
no_letter	IOQSXZ

The module keyboard causes pyscad to import bga.py and then call the 'part'
method with the data supplied in the .pscad file. If a module contains multiple
parts, a part keyword can be used to indicate which method should be called.

All units are assumed to be mm, but can be suffixed with the following
modifiers:

", in, inch, inches
mil, mils, thou
nm
um
mm
m

About

OpenSCAD-like PCB footprint generator

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published