Examples
Blinky
An MCU pin, a series resistor and an LED: the board everybody builds first. Read it after divider/, because it is the first example where the parts have interfaces rather than bare pads.
The program
Section titled “The program”blinky.py declares its own parts. MCU is a Part with a
PowerIn, a Signal, three pins and a PinMap joining the two:
power = PowerIn(voltage=3.3 * V, current_demand=30 * mA)blink = Signal()
pinmap = PinMap({"power.vcc": "VDD", "power.gnd": "VSS", "blink.line": "PA5"})The pin map is what makes self.header.dc >> self.mcu.power mean something.
One connection between two typed surfaces lowers to the pads that carry it. The
netlist below is that lowering, not a second description of it.
The constraint is the point of the example:
require(self.series.resistance >= 150 * Ohm)require(self.indicator.forward_current <= 20 * mA)The 330 Ohm is not defended by the comment beside it. The bound it has to satisfy is written down, so replacing the LED re-decides the question instead of inheriting an old answer.
What comes out
Section titled “What comes out”6 parts, 4 nets, 47 entities, 6 checks. None failed, one undecided.
That undecided one is worth reading in out/checks.txt: the
board’s supply surface has no current_demand on it, so “does the source
carry the load?” has no answer. The kernel says so rather than passing the check
on an assumed number.
out/blinky.net: the KiCad netlistout/netlist.txt,out/graph.txt
Running it
Section titled “Running it”fang check examples/blinky/blinky.pyfang netlist examples/blinky/blinky.pyfang view examples/blinky/blinky.py power -o power.svgThe whole program
Section titled “The whole program”"""The smallest program that drives something: an MCU pin, a resistor, an LED.Show 5 more lines
The board everybody builds first. What it shows is the shape of a Fang program:declared surfaces, connections between them and a constraint that states theengineering intent rather than the answer."""
from fang.interfaces import Pin, PinMap, PowerIn, PowerOutfrom fang.lang import Ohm, Part, Signal, System, V, mA, mW, nF, requirefrom fang.parts import LED, Capacitor, Resistor
class MCU(Part): """A microcontroller, reduced to the one output this board uses."""
designator_prefix = "U"
power = PowerIn(voltage=3.3 * V, current_demand=30 * mA) blink = Signal()
VDD = Pin("VDD", role="power", number="1") VSS = Pin("VSS", role="ground", number="8") PA5 = Pin("PA5", role="data", number="5")
pinmap = PinMap({"power.vcc": "VDD", "power.gnd": "VSS", "blink.line": "PA5"})
class PowerHeader(Part): """Two pins and a rail: the board's power has to arrive on a pad."""
designator_prefix = "J"
dc = PowerOut(voltage=3.3 * V, current_capability=200 * mA)
VCC = Pin("VCC", role="power", number="1") GND = Pin("GND", role="ground", number="2")
pinmap = PinMap({"dc.vcc": "VCC", "dc.gnd": "GND"})
class Blinky(System): supply = PowerIn(voltage=3.3 * V, current_capability=200 * mA)
header = PowerHeader(package="PinHeader_1x02_P2.54mm") mcu = MCU(package="SOIC-8") series = Resistor(resistance=330 * Ohm, power_rating=125 * mW, package="R_0603") indicator = LED( forward_voltage=2 * V, forward_current=10 * mA, package="LED_0603" ) bypass = Capacitor(capacitance=100 * nF, voltage_rating=16 * V, package="C_0402")
def architecture(self): self.supply >> self.header.dc self.header.dc >> self.mcu.power
# The pin drives the anode through the series resistor; the cathode # returns to the rail's ground rather than to a second ground of its own. self.mcu.blink >> self.series.p1 self.series.p2 >> self.indicator.p1 self.indicator.p2 >> self.header.dc.gnd
# Decoupling belongs to the pin it decouples, so a checker can find it. self.mcu.power.vcc >> self.bypass.p1 self.mcu.power.gnd >> self.bypass.p2
def constraints(self): # (3.3 V - 2.0 V) / 330 Ohm is about 4 mA: visible, and inside what a # GPIO will source. Both bounds are stated; neither is computed here. require(self.series.resistance >= 150 * Ohm) require(self.indicator.forward_current <= 20 * mA)The files it writes
Section titled “The files it writes”The parts, then the nets and the pads on them.
C1 100 nF Package:C_0402DS1 2 V Package:LED_0603J1 PowerHeader Package:PinHeader_1x02_P2.54mmR1 330 Ohm Package:R_0603U1 MCU Package:SOIC-8Net-(C1-Pad1) C1.1 J1.VCC U1.VDDNet-(C1-Pad2) C1.2 DS1.K J1.GND U1.VSSNet-(DS1-PadA) DS1.A R1.2Net-(R1-Pad1) R1.1 U1.PA5Every check that ran, and every one left undecided.
UNDECIDED interface_compatibility: current capability is undecided on power_input: current_demand unknown6 checks, 0 failed, 1 undecidedWhat the elaborated graph contains, by entity kind.
1 block 5 component 14 connection 2 constraint 4 interface 11 pin 10 port 47 totalsnapshot sha256:dab7fbedff03ec019e23be5984d535093cf576f8c12c787f2b41cd448315f8a3All of it, including the KiCad netlist, is in
examples/blinky/out/. Rebuild it with:
fang build examples/blinky/blinky.py