Erbui Grammar
This document describes what sequence of tokens form valid inputs of the language.
How to Read the Grammar
The notation used to describe the formal grammar of erbui has the following conventions:
An arrow (→) is used to mark grammar productions and can be read as “can consist of”,
Alternative grammar productions are either separated by verticals bars (|) or are broken into multiple grammar production rules lines,
Keywords and symbols are indicated using
bold inline codestyle text,Optional syntactic categories and literals are marked by a trailing subscript (opt),
Syntactic category or literal repetitions of 0 or more are marked by a trailing subscript (0+),
Syntactic category or literal repetitions of 1 or more are marked by a trailing subscript (1+).
Global namespace
The global namespace is the root of the grammar. One and only one module declaration is valid.
Grammar
global-namespace → module-declaration
module
A module defines a physical module, a unique piece of hardware to produce.
it is a set of multiple control, image, label, width, material, etc. declarations.
Grammar
module-declaration →
modulemodule-name module-inheritance-clauseopt{module-entity0+}
module-name → identifier
module-inheritance-clause →extendsidentifier
module-entity → board-declaration
module-entity → width-declaration
module-entity → material-declaration
module-entity → route-declaration
module-entity → header-declaration
module-entity → footer-declaration
module-entity → line-declaration
module-entity → label-declaration
module-entity → sticker-declaration
module-entity → image-declaration
module-entity → control-declaration
module-entity → alias-declaration
module-entity → exclude-declaration
Extensions
The module inheritance clause loads the content of the standard library module with its identifier name, and populates the extended module with all the inherited module definitions.
For example:
// In standard library
module Foo {
width 12hp
label "Some Text"
}
// User
module Bar extends Foo {
header { label "BAR" }
}
Is equivalent to:
module Bar {
width 12hp
label "Some Text"
header { label "BAR" }
}
material
A material defines the actual material used to produce the module front panel.
Grammar
material-declaration →
materialmaterial-name material-coloropt
material-name →pcb
material-name →aluminum
material-name →brushed_aluminum
material-color →natural
material-color →black
route
A route defines the way the front PCB is routed, wire if not specified (which requires hand soldering).
manual allows to manually route the front PCB or use an autorouteur. In that case, all the
hand soldering pads are removed to leave more space for routing.
Grammar
route-declaration →
routeroute-mode
route-mode →wire
route-mode →manual
board
A board defines the board used for the back panel. Each board comes with
a specific set of digital, analog and audio pins and their associated names for both inputs and
outputs.
A board definition can be be made inline as well, and is typically used for custom boards.
Grammar
board-declaration →
boardidentifier
board-declaration →board{board-entity0+}
board-entity → format-declaration
board-entity → board-class-declaration
board-entity → board-include-declaration
board-entity → board-pcb-declaration
board-entity → board-sch-declaration
board-entity → board-pin-declaration
board-entity → board-pins-declaration
format-declaration →formatformat-name
format-name →3u
format-name →1590bb2_portrait
board-class-declaration →classstring-literal
board-include-declaration →includestring-literal
board-pcb-declaration →pcbstring-literal board-pcb-bodyopt
board-pcb-body →{board-pcb-entity0+}
board-pcb-entity → board-pcb-side-declaration
board-pcb-side-declaration →sideboard-pcb-side-name
board-pcb-side-name →face
board-pcb-side-name →left
board-pcb-side-name →top
board-pcb-side-name →right
board-pcb-side-name →bottom
board-sch-declaration →schstring-literal
board-pin-declaration →pinidentifier board-pin-clause
board-pins-declaration →pinsidentifier board-pin-range board-pin-clause
board-pin-range →..integer-literal
board-pin-clause → board-pin-kinds-declaration{board-pin-entity0+}
board-pin-entity → board-pin-bind-declaration
board-pin-entity → board-pin-type-declaration
board-pin-kinds-declaration → control-kind
board-pin-kinds-declaration → control-kind,board-pin-kinds-declaration
board-pin-kinds-declaration →normalling
board-pin-bind-declaration →bindstring-literal
board-pin-type-declaration →typeboard-pin-type-name
board-pin-type-name →gpio
board-pin-type-name →pwm
board-pin-type-name →dac
See individual boards reference for the available pins configuration for each board.
Inline boards replicate the board definition.py python format, but using erbui syntax.
width
width defines the module width in HP.
If a board is defined but no width is defined, then the actual width will be inherited from the board width.
Only a specific set of integer HP widths are valid.
Grammar
width-declaration →
widthdistance-literal
header
The header defines a region at the top of the module, typically used for the
module logo.
Grammar
header-declaration →
header{header-entity0+}
header-entity → label-declaration
header-entity → image-declaration
control
A control is an element of the module that is generally apparent on the front panel
and with which the end-user can interact with.
Grammar
control-declaration →
controlcontrol-name control-kind{control-entity0+}
control-name → identifier
control-entity → mode-declaration
control-entity → position-declaration
control-entity → rotation-declaration
control-entity → style-declaration
control-entity → label-declaration
control-entity → image-declaration
control-entity → pins-declaration
control-entity → pin-declaration
control-entity → normalling-declaration
Language Bindings
control-name is exported to the target language used to develop the module DSP, such as C++ or Max.
For example the following erbui source code:
module Foo {
control vco_freq Pot { ... }
}
Exports the vco_freq in C++:
void process () {
float val = ui.vco_freq;
}
alias
An alias gives an alternative name to a control name. It is typically used when extending
a standard library board, to give appropriate names to the entities of a module.
Grammar
alias-declaration →
aliasidentifier alias-reference
alias-reference → identifier
For example:
// Standard library daisy_field.erbui
module daisy_field {
...
control pot1 Pot { ... }
control pot2 Pot { ... }
}
// User code Foo.erbui
module Foo extends daisy_field {
alias vco_freq pot2
}
// Foo.cpp
void process ()
{
float freq_val = ui.pot1; // not great
float freq_val2 = ui.vco_freq; // better
}
exclude
An exclude allows to prevent the use of one or more pins to be used for the entire module.
It is typically used when a pin is colliding with a control on the board, but it makes more
sense to exclude the pin rather than move the control.
Grammar
exclude-declaration →
excludeexclude-entity
exclude-entity → pins-declaration
exclude-entity → pin-declaration
For example:
module Foo {
board kivu12
exclude pins P1, P2
control pot1 Pot { ... }
control pot2 Pot { ... }
}
The pins of pot1 and pot2 will be respectively P3 and P4, instead of P1 and P2 which
are excluded.
mode
A mode defines a range of values presented by the control.
Grammar
mode-declaration →
modemode-value
mode-value →normalized
mode-value →bipolar
normalized
normalized represents a range of values from 0 to 1.
When the control has a jack connector for inputs or outputs,
it maps the value linearly from 0V to 5V.
This is the default mode for Pot and Trim.
style
A style instructs the hardware parts to use for a control.
This can represent the component part as mounted on the PCB
as well as one or more decoration elements that the end-user will manipulate,
such as a style of knob.
The style is given as a list of keywords, which represents the developer intent. The intent can represent for example the color of a LED, or the brand and size of a pot.
Given a manufacturer, each control kind (eg. Pot, Led, AudioIn) as a list of sets of
style keywords. When the developer specifies a list of keywords representing their intent,
the style engine selects the first set of keywords in the manufacturer list which matches
best the developer-defined set of keywords.
When no style is specified, the first item of the manufacturer list is returned, which is designed so that the resulting combination of parts is the most popular for this control kind.
line
A line is a graphic element printed on the front panel, usually used to indicate a conceptual
link between a pair of controls.
Grammar
line-declaration →
line{line-entity0+}
line-entity → position-declaration
line-entity → layer-declaration
offset
An offset represents a relative shift from a position, typically used to reposition a control’s label.
Grammar
offset-declaration →
offsetdistance-literal,distance-literal
position
A position represents the position of a control on the front panel.
Usually, the position is relative to the natural center of the control, when applicable.
layer
A layer represents how a graphic element is rendered on the front panel.
It can be one of:
silkscreen, this is the default,translucence.
silkscreen uses typically UV printed inks on the front panel.
translucence is only meaninful when material pcb is selected.
It removes the solder mask and copper fill of the shape of the parent,
so only the PCB fiberglass is left, allowing light to pass through.
For example:
module Foo {
material pcb
image "silkscreen.svg"
image "translucence.svg" { layer translucence }
}
Grammar
layer-declaration →
layersilkscreen
layer-declaration →layertranslucence
sticker
A sticker represents a virtual sticker glued on the front panel.
It is usually used in conjunction of alias to display the real name of a value on top of
the default board one.
The sticker is only displayed when using the simulator. In particular, it is not present in
the generated front panel files for hardware production.
Grammar
sticker-declaration →
stickerstring-literal sticker-bodyopt
sticker-body →{sticker-entity0+}
sticker-entity → position-declaration
sticker-entity → positioning-declaration
sticker-entity → offset-declaration
label
A label is a piece of text printed on the front panel, and usually represents the name of
the associated control, or group of controls.
A label can be either defined in a control with its positioning relative to the control, or
can be defined freely in the module with a position relative to the module.
Grammar
label-declaration →
labelstring-literal label-bodyopt
label-body →{label-entity0+}
label-entity → position-declaration
label-entity → positioning-declaration
label-entity → offset-declaration
label-entity → layer-declaration
image
An image is a picture printed on the front panel, and is usually used to make a complete
custom front panel design.
The path represents a Scalable Vector Graphics (SVG)
file relative to the erbui file where the image definition takes place.
Grammar
image-declaration →
imagepath-literal image-bodyopt
image-body →{image-entity0+}
image-entity → layer-declaration
pin
A pin represents the physical board pin used by a control.
pins
A pin represents a set of physical board pins used by a control.
Grammar
pins-declaration →
pinspins-argument-list
pins-argument-list → pin-name
pins-argument-list → pin-name,pins-argument-list
See individual boards reference for the available pins configuration for each board.
The pins property is only supported for controls that support more than one data pin.
See individual controls reference for a list of pins for each control.
normalling
A normalling represents a link from the current control to the
referenced control or board pin.
The normalling property is only supported for GateIn, CvIn and AudioIn control kinds.
Grammar
normalling-declaration →
normallingcontrol-reference
normalling-declaration →normallingnothing
normalling-declaration →normallingpinboard-pin-reference
control-reference → identifier
board-pin-reference → identifier
normalling allows to take the signal of an unplugged input from another input, “nothing”, or a default non-zero value.
Nothing allows to detect jack detection.
For example:
module MonoOrStereo {
...
control input_left AudioIn { ... }
control input_right AudioIn {
...
normalling input_left
}
}
In the example above, when no audio jack is connected into the right input,
the signal seen on input_right will be the signal of input_left.
This typically allows to a module to work with mono or stereo inputs, or to detect if a user has connected a jack on a clock input to lock tempo to the rest of the system.
Normalling from a pin allows to define a virtual pin which bound function returns the default voltage when the input is unplugged. This allows to provide a non-zero default value for an input when the underlying jack is unplugged. This returned voltage must match the hardware implementation, for the simulator to conform with the hardware behavior.
For example:
module Synth {
...
board {
...
pin VELO1 normalling { bind "velo1()" } // returns 5 (volts)
}
control velocity_cv CvIn {
...
normalling pin VELO1
}
}
In the example above, the custom board must define a VELO1 pin which will be
5V in practice. When generating the hardware, the system will ensure to connect
this pin to the normalling input of the hardware part.
Then, in the simulator and on the real hardware, reading velocity_cv will return 1.f
when the input jack is not plugged (instead of 0.f).
positioning
A positioning represents a positioning of a graphic element relative to its control center.
It is usually used to position labels for a control.
Grammar
positioning-declaration →
positioningpositioning-name
positioning-name →center
positioning-name →left
positioning-name →top
positioning-name →right
positioning-name →bottom
center
This positioning centers the graphic element with the center of its control.
left
This positioning places the graphic element to the left of its control.
top
This positioning places the graphic element to the top of its control.
right
This positioning places the graphic element to the right of its control.
bottom
This positioning places the graphic element to the bottom of its control.