Core Language

Nets

class pcbdl.Net(name=None)[source]
__init__(name)[source]

Nets can be created by calling Net("SOME_NAME").

If used in more places, you might want to save it in a variable:

gnd = Net("GND")

The name in the “” gets automatically capitalized, but it’s good practice to do it anyway. Though the variables should stay lowercase to conform to the python style guide.

Also note that the variable names should not necessarily have to match the net name. In some cases it might make more sense to have a shorter name locally for a net instead of the full long global name. Example: mosi = Net("AP_SPI2_MOSI")

__lshift__(pin or pins)[source]
__rshift__(pin or pins)[source]

Pins can be connected to nets using the << and >> operators:

gnd << device1.GND

A list of pins can also be given (and they will be added in the same group):

gnd << (device1.GND, device2.GND)
gnd >> (
    device3.GND,
    device4.GND,
)

The direction of the arrows is stored, but it doesn’t really mean anything yet. You’re free to use it as a hint on which way the signal is flowing (low impedance toward high impedance).

Returns

A special version of this Net that will actually remember the group that we’re currently attaching to. This way Pins added in the same line, even if alternating operators, will remember they were grouped:

gnd << device1.GND >> regulator1.GND
gnd << device2.GND >> regulator2.GND

Now device1 and regulator1’s GND pin are remembered that they were grouped. The grouping might be significant, maybe as a hint, to the reader. This is a little bit of metadata that allows prettier exports (eg: SVG output will probably draw a real wire between those pins instead of airwires).

property connections

A tuple of pins connected to this net.

Useful in the interpreter and/or when you want to inspect your schematic:

>>> gnd.connections
(U1.GND, VREG1.GND, U2.GND, VREG2.GND)
property grouped_connections

Similar to connections, but this time pins that were connected together stay in groups:

>>> pp1800.grouped_connections
((U1.GND, VREG1.GND), (U2.GND, VREG2.GND))

Parts

class pcbdl.Part(value=None, refdes=None, package=None, part_number=None, populated=True)[source]

This is the base class for any new Part the writer of a schematic or a part librarian has to make.

class Transistor(Part):
    REFDES_PREFIX = "Q"
    PINS = ["B", "C", "E"]
property refdes

Reference designator of the part. Example: R1, R2.

It’s essentially the unique id for the part that will be used to refer to it in most output methods.

PINS = []

This is how the pins of a part are defined, as a list of pins.

Each pin entry can be one of:

  • Pin

  • tuple of names which will automatically be turned into a Pin

  • just one string, representing a pin name, if one cares about nothing else.

So these are all valid ways to define a pin (in decreasing order of detail), and mean about the same thing:

PINS = [
    Pin("1", ("GND", "GROUND"), type=PinType.POWER_INPUT),
    ("GND", "GROUND"),
    "GND",
]

See the Pins Section for the types of properties that can be defined on each Pin entry.

classmethod _postprocess_pin(pin)[source]

It’s sometimes useful to process the pins from the source code before the part gets placed down. This method will be called for each pin by each subclass of a Part.

Good uses for this:

  • Raise the importance of the second name in a connector, so the more semantic name is the primary name, not the pin number:

    PINS = [
        ("P1", "Nicer name"),
    ]
    _postprocess_pin = Pin.second_name_important
    
  • Populate alternate functions of a pin if they follow an easy pattern.

  • A simple programmatic alias on pin names without subclassing the part itself.

pins = {}

Once the Part is instanced (aka populated on the schematic), our pins become real too (they turn into PartInstancePins). This is a dict like object where the pins are stored. One can look up pins by any of its names:

somechip.pins["VCC"]

Though most pins are also directly populated as a attributes to the part, so this is equivalent:

somechip.VCC

The pins list can still be used to view all of the pins at once, like on the console:

>>> diode.pins
(D1.VCC, D1.NC, D1.P1, D1.GND, D1.P2)
REFDES_PREFIX = 'UNK'

The prefix that every reference designator of this part will have.

Example: "R" for resistors, "C" for capacitors.

The auto namer system will eventually put numbers after the prefix to get the complete refdes.

pin_names_match_nets = False

Sometimes when connecting nets to a part, the pin names become very redundant:

Net("GND") >> somepart.GND
Net("VCC") >> somepart.VCC
Net("RESET") >> somepart.RESET

We can use this variable tells the part to pick the right pin depending on the variable name, at that point the part itself can be used in lieu of the pin:

Net("GND") >> somepart
Net("VCC") >> somepart
Net("RESET") >> somepart
pin_names_match_nets_prefix = ''

When pin_names_match_nets is active, it strips a little bit of the net name in case it’s part of a bigger net group:

class SPIFlash(Part):
    pin_names_match_nets = True
    pin_names_match_nets_prefix = "SPI1"
    PINS = ["MOSI", "MISO", "SCK", "CS", ...]
...
Net("SPI1_MOSI") >> spi_flash # autoconnects to the pin called only "MOSI"
Net("SPI1_MISO") << spi_flash # "MISO"
Net("SPI1_SCK")  >> spi_flash # "SCK"
Net("SPI1_CS")   >> spi_flash # "CS"

Pins

pcbdl.Pin

alias of pcbdl.base.PinFragment

class pcbdl.base.PinFragment(names_or_numbers=(), names_if_numbers=None, *args, **kwargs)[source]

This is the fully featured (as opposed to just a tuple of parameters) element of PINS at the time of writing a Part. Saves all parameters it’s given, merges later once the Part is fully defined.

Warning

Just like the name implies this is just a fragment of the information we need for the pin. It’s possible the Part needs to be overlayed on top of its parents before we can have a complete picture. Ex: this could be the pin labeled “PA2” of a microcontroller, but until the part is told what package it is, we don’t really know the pin number.

static second_name_important(pin)[source]

Swap the order of the pin names so the functional (second) name is first.

Used as a Part._postprocess_pin filter.

class pcbdl.base.PartClassPin(names, numbers, type=<PinType.UNKNOWN: 0>, well=None)[source]

Pin of a Part, but no particular Part instance. Contains general information about the pin (but it could be for any part of that type), nothing related to a specific part instance.

class pcbdl.base.PartInstancePin(part_instance, part_class_pin, inject_number=None)[source]

Particular pin of a particular part instance. Can connect to nets. Knows the refdes of its part.

property net

The Net that this pin is connected to.

If it’s not connected to anything yet, we’ll get a fresh net.

__lshift__(another pin or pins)[source]
__rshift__(another pin or pins)[source]

Syntactic sugar for pin.net << another_pin or pin.net >> another_pin:

# Instead of
Net() >> somepart.BUTTON << somebutton.OUTPUT

# Or
Somepart.BUTTON.net << somebutton.OUTPUT

# One can just write
somepart.BUTTON << somebutton.OUTPUT

Other