JITX Patterns Cheat Sheet
The JITX language is embedded into the LB Stanza Programming Language. A comprehensive guide to learning stanza can be found in the reference, Stanza by Example. A short guide on stanza expressions and syntax can also be read here.
Common Code Patterns
for
loops
A for loop takes the form
for <thing> in <sequence> <op> :
<body>
Where thing
is an identifier, sequence
is an expression of type Seqable
, and op
is an "operating" function that applies body
to thing
. Here are some common examples :
val values = [1, 2, 3]
for value in values do :
println(value)
; prints :
; 1
; 2
; 3
do
is the most common operating expression and just applies the body of the loop to the value in the sequence.
Another common operator is filter
, which is used to loop over the sequence
and remove items.
val values = [1, 2, 3]
val odds =
for value in values filter :
value % 2 != 0
for odd in odds do :
println(odd)
; prints :
; 1
; 3
More examples of for loops can be found in Stanza by Example, and a list of operating functions is available in the reference.
match
expressions
The match
expression is a conditional expression that evaluates one of multiple branches depending on the types of its arguments. The most common form is a single argument match.
defn my-function (arg:Int|Double|True|False) :
match(arg) :
(i:Int) :
println("arg is an Int:%_" % [i])
(d:Double) :
println("arg is a Double:%_" % [d])
(b:True|False) :
println("arg is a boolean:%_" % [b])
match
can take multiple arguments.
defn my-function (x:Int|Double, y:Int|Double) :
match(x, y) :
(x:Int, y:Int) :
println("x and y are Ints.")
(x:Double, y:Double) :
println("x and y are Doubles.)
(x, y) :
println("x and y are of different types!)
A common pattern is something like this :
defn my-function (arg:Int|False) :
match(arg) :
(arg:Int) :
do-something(arg)
(f:False) :
; do nothing
false
A shorthand for this syntax is
defn my-function (arg:Int|False) :
match(arg:Int) :
do-something(arg)
switch
expressions
The switch
expression is another conditional expression that evaluates multiple branches, it's syntactic sugar for chains of if/else if expressions.
defn arrive-or-leave (arg:String) :
switch(arg) :
"hello" :
hello()
"goodbye" :
goodbye()
else :
fatal("The caller has bad manners.")
supports
statements
Supports statements declare what bundle(s) a component or module supports and how the bundle pins are mapped to the ports of the component or module.
; Bundles may be used inside pcb-components or
; pcb modules
; The mapping goes
; bundle.pin-ref => self.pin-ref
supports bundle :
bundle.p[1] => self.p[2]
; ... rest of mappings to the bundle ...
requires
statements
Requires statements are used in pcb-module
definitions to define what support
s they need.
; inside pcb-module
require <ref> : <bundle> from <instance>
The pin solver will automatically map pins that supports
the bundle
that the module requires to an alias, ref
.
In addition to using require
inside of a pcb-module
, require
statements can be "chained" inside of supports
statements.
pcb-component mcu :
port p: pin[128]
for n in 10 to 30 do :
supports gpio :
gpio.p => self.p[n]
supports spi-controller():
require io : gpio[4]
spi-controller().copi => io[0].p
spi-controller().cipo => io[1].p
spi-controller().cs => io[2].p
spi-controller().sck => io[3].p
pin-properties
tables
pin-properties
tables are a mechanism for declaring metadata about the pins in a pcb-component
. It is used for commands like assign-landpattern
, assign-symbol
, and make-box-symbol
.
; Declare pin properties: the names of pins and pads they are mapped
; to on the associated landpattern
pcb-component component :
;Each row has format:
pin-properties :
[pin:Ref | pads:Int ... ]
[a | 1 ]
[b | 2 ]
[c | 3 ]
[gnd | 4 5 6 7 8 ]
[d+ | 9 ]
[d- | 10 ]
make-box-symbol()
assign-landpattern(mylandpattern)
pcb-component
definitions
See the reference for more.
pcb-component component :
name = "My awesome component"
mpn = "MPN"
manufacturer = "Manufacturer"
description = "This is an example component."
; ... component statements ...
pcb-module
definitions
See the reference for more.
pcb-module module :
; Define some metadata of the module
name = "My Module"
description = "This is an example module"
; Declare some ports
port io: bundle
; Declare some instances
inst U: component
; Net ports and instances together
net (io.p[1], U.p[1])
; Perhaps add some layer geometry
layer(Silkscreen("F-Silk", Top)) = Text("REV 1.0", 2.54, C, loc(0.0, 0.0))
; Add instances to schematic groups
schematic-group(U) = grouped-insts
; Add the instances to schematic groups
pcb-landpattern
definitions
See the reference for more.
pcb-landpattern my-landpattern :
; define a pad
pad p[1] : smd-pad(Circle(1.0)) at loc(0.0, 0.0) on Top
; Add custom soldermask layers
layer(SolderMask(Top)) = Rectangle(1.25, 1.25)
pcb-component
to pcb-symbol
mappings
Symbol pins are mapped to component pins using the following syntax :
pcb-component my-resistor :
port p: pin[[1, 2]]
; sym is an expression corresponding to a generated
; pcb-symbol
val sym = resistor-sym()
; The mapping is:
; <component-pin> => <symbol>.<symbol-pin>
symbol =
sym(p[1] => sym.p[1],
p[2] => sym.p[2])
pcb-component
to pcb-landpattern
mappings
Landpattern pins are mapped to component pins using the following syntax :
pcb-component my-resistor :
port p: pin[[1, 2]]
; lp is an expression corresponding to a generated
; pcb-landpattern
val lp = ipc-two-pin-landpattern("0201")
; The mapping is:
; <component-pin> => <landpattern>.<landpattern-pad>
landpattern =
lp(p[1] => lp.p[1],
p[2] => lp.p[2])
Getting and setting properties
; set a property
property(self.property-name) = expression
; get a property
val property = property(self.property-name)
; check if a property is set
has-property?(self.property-name)
; optionally check if a property is set and
; perform some logic with the value
match(property?(self.property-name)) :
(one:One) :
val property = value(one)
(none:None) :
; property is not set
Adding passive components
ocdb/utils/generic-components
has a few generators for querying jellybean components from
the JITX parts database. See the design variables reference for configuration with
global design parameters.
defpackage my-design :
import jitx
import jitx/commands
import ocdb/utils/design-vars
import ocdb/utils/generic-components
; define the minimum package size for the design
MIN-PKG = "0601"
pcb-module module :
; Drop some passives in a module
; Query a generic 1k ohm chip resistor
inst R1 : chip-resistor(1.0e3)
; Query a generic 1k ohm chip resistor with 5% tolerance
inst R2 : chip-resistor(1.0e3, 0.05)
; Query a generic 4.7nF ceramic cap
inst C1 : ceramic-cap(4.7e-9)
; Query a generic 4.7nF ceramic cap with 5% tolerance
inst C1 : ceramic-cap(4.7e-9)
Named net
s
Nets can be given a name, but it must have one character of whitespace between the name and arguments!
pcb-module module :
net name (a, b, c)
; net name(a, b,c) <--- invalid!