Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/code-prettify/run_prettify.js
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,7 @@ var IN_GLOBAL_SCOPE = false;
"set," +
"severity," +
"signal," +
"signed," +
"size," +
"sizeof," +
"stack," +
Expand All @@ -504,6 +505,7 @@ var IN_GLOBAL_SCOPE = false;
"topology," +
"type," +
"unmatched," +
"unsigned," +
"update," +
"warning," +
"with," +
Expand Down
129 changes: 123 additions & 6 deletions docs/fpp-spec.html
Original file line number Diff line number Diff line change
Expand Up @@ -1301,6 +1301,7 @@ <h3 id="Lexical-Elements_Reserved-Words">3.1. Reserved Words</h3>
set
severity
signal
signed
size
sizeof
stack
Expand All @@ -1316,6 +1317,7 @@ <h3 id="Lexical-Elements_Reserved-Words">3.1. Reserved Words</h3>
true
type
unmatched
unsigned
update
warning
with
Expand Down Expand Up @@ -3697,8 +3699,12 @@ <h4 id="Definitions_Struct-Definitions_Syntax">5.13.1. Syntax</h4>
<p><em>struct-type-member-sequence</em> is an <a href="#Element-Sequences">element sequence</a>
in which the elements are struct type members, and the terminating
punctuation is a comma.
A <strong>struct type member</strong> has the following syntax:</p>
A <strong>struct type member</strong> has one of the following two forms:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>A <strong>typed member</strong>:</p>
<div class="paragraph">
<p><a href="#Lexical-Elements_Identifiers"><em>identifier</em></a> <code>:</code>
<em>[</em>
Expand All @@ -3709,6 +3715,20 @@ <h4 id="Definitions_Struct-Definitions_Syntax">5.13.1. Syntax</h4>
<code>format</code> <a href="#Expressions_String-Literals"><em>string-literal</em></a>
<em>]</em></p>
</div>
</li>
<li>
<p>A <strong>bit field member</strong>:</p>
<div class="paragraph">
<p><a href="#Lexical-Elements_Identifiers"><em>identifier</em></a> <code>:</code>
( <code>signed</code> | <code>unsigned</code> )
<a href="#Expressions"><em>expression</em></a>
<em>[</em>
<code>format</code> <a href="#Expressions_String-Literals"><em>string-literal</em></a>
<em>]</em></p>
</div>
</li>
</ol>
</div>
</div>
<div class="sect3">
<h4 id="Definitions_Struct-Definitions_Semantics">5.13.2. Semantics</h4>
Expand All @@ -3720,7 +3740,7 @@ <h4 id="Definitions_Struct-Definitions_Semantics">5.13.2. Semantics</h4>
identifier appearing in the struct type member sequence must be distinct.</p>
</div>
<div class="paragraph">
<p>For each member <em>m</em>,</p>
<p>For each typed member <em>m</em>,</p>
</div>
<div class="ulist">
<ul>
Expand Down Expand Up @@ -3748,6 +3768,59 @@ <h4 id="Definitions_Struct-Definitions_Semantics">5.13.2. Semantics</h4>
</ul>
</div>
<div class="paragraph">
<p>For each bit field member <em>m</em>,</p>
</div>
<div class="ulist">
<ul>
<li>
<p>The keyword <code>signed</code> or <code>unsigned</code> specifies the <strong>signedness</strong> of <em>m</em>.</p>
</li>
<li>
<p>The expression following the keyword specifies the <strong>bit width</strong>
\$w_m\$ of <em>m</em>.
The expression must have a
<a href="#Types_Internal-Types_Numeric-Types">numeric type</a>, and it must
evaluate to a value \$w_m\$ after conversion to
<a href="#Types_Internal-Types_Integer"><em>Integer</em></a>, with
\$1 &lt;= w_m &lt;= 64\$.</p>
</li>
<li>
<p>The type \$T_m\$ of <em>m</em> is the
<a href="#Types_Primitive-Integer-Types">primitive integer type</a>
with the specified signedness and with the smallest width
greater than or equal to \$w_m\$.
For example, the type of a member <code>unsigned 4</code> is <code>U8</code>, and
the type of a member <code>signed 12</code> is <code>I16</code>.
This type governs the use of the member in expressions and its
representation in generated code.</p>
</li>
<li>
<p>The value stored in <em>m</em> must be representable in \$w_m\$ bits:
in the range \$[0, 2^(w_m)-1]\$ if <em>m</em> is unsigned, and in the range
\$[-2^(w_m-1), 2^(w_m-1)-1]\$ if <em>m</em> is signed.
In particular, if the default value of the struct type specifies a
value for <em>m</em>, then the value must lie in this range.</p>
</li>
<li>
<p>A bit field member represents a single value; it may not have a
size expression <code>[</code> <em>e</em> <code>]</code>.</p>
</li>
<li>
<p>The optional format specifier behaves as it does for a typed
member.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>The bit width affects only the serialized form of the struct type,
not the in-memory representation.
Each maximal sequence of consecutive bit field members in the struct
type member sequence forms a <strong>bit field group</strong>.
The members of a bit field group are packed into a sequence of bytes
as described in the section on
<a href="#Types_Serialized-Sizes">serialized sizes</a>.</p>
</div>
<div class="paragraph">
<p>The expression following the keyword <code>default</code> is optional.
If present, it specifies the <a href="#Types_Default-Values">default value</a>
associated with the type.
Expand Down Expand Up @@ -3792,7 +3865,20 @@ <h4 id="Definitions_Struct-Definitions_Examples">5.13.3. Examples</h4>
# The default value of D stores 1 into each of the 3 elements of x
struct D {
x: [3] U32
} default { x = 1 }</code></pre>
} default { x = 1 }

# Defines a struct type E with two bit field members and one
# typed member.
# a and b form a bit field group of 12 bits, which is packed
# into 16 serialized bits (12 bits of data and 4 zero pad bits).
# The type of a is U8; the type of b is I16.
# The serialized size of E is 6 bytes: 2 bytes for the bit field
# group and 4 bytes for x.
struct E {
a: unsigned 3
b: signed 9
x: U32
}</code></pre>
</div>
</div>
</div>
Expand Down Expand Up @@ -11554,8 +11640,11 @@ <h3 id="Types_Serialized-Sizes">17.19. Serialized Sizes</h3>
<li>
<p>If <em>T</em> is a
<a href="#Types_Struct-Types">struct type</a>, then <em>s</em>
the sum of the serialized sizes of the members of <em>T</em>.
For each member <em>m</em> with type \$T_m\$:</p>
the sum of the serialized sizes of the members of <em>T</em>
and of the
<a href="#Definitions_Struct-Definitions">bit field groups</a> of <em>T</em>,
in declaration order.
For each member <em>m</em> with type \$T_m\$ that is not a bit field member:</p>
<div class="ulist">
<ul>
<li>
Expand All @@ -11569,6 +11658,34 @@ <h3 id="Types_Serialized-Sizes">17.19. Serialized Sizes</h3>
</div>
</li>
<li>
<p>Each bit field group <em>G</em> of a struct type is serialized as a unit,
as follows:</p>
<div class="ulist">
<ul>
<li>
<p>Let <em>w</em> be the sum of the bit widths of the members of <em>G</em>.
The serialized size of <em>G</em> is <em>w</em> divided by 8, rounded up to the
nearest integer, in bytes.</p>
</li>
<li>
<p>The members of <em>G</em> are packed in declaration order into
the serialized bytes, from the most significant bit of the first
byte towards the least significant bit of the last byte,
with no intervening bits.
Each member occupies exactly its bit width, using the standard
binary representation of an unsigned integer or the two&#8217;s complement
representation of a signed integer.</p>
</li>
<li>
<p>If <em>w</em> is not a multiple of 8, then the low-order bits of the
last byte that are not occupied by any member are <strong>pad bits</strong>.
Pad bits are zero in the serialized form and are ignored during
deserialization.</p>
</li>
</ul>
</div>
</li>
<li>
<p>If <em>T</em> is an
<a href="#Types_Alias-Types">alias type</a>, then <em>s</em> is the serialized size of the
<a href="#Types_Underlying-Types">underlying type</a> of <em>T</em>.</p>
Expand Down Expand Up @@ -13309,7 +13426,7 @@ <h3 id="Analysis-and-Translation_Translation-Tools">23.4. Translation Tools</h3>
</div>
<div id="footer">
<div id="footer-text">
Last updated 2026-08-19 10:10:16 -0700
Last updated 2026-08-27 04:19:50 UTC
</div>
</div>
<script src="code-prettify/run_prettify.js"></script>
Expand Down
69 changes: 67 additions & 2 deletions docs/spec/Definitions/Struct-Definitions.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ _[_ `default` <<Expressions,_expression_>> _]_
_struct-type-member-sequence_ is an <<Element-Sequences,element sequence>>
in which the elements are struct type members, and the terminating
punctuation is a comma.
A *struct type member* has the following syntax:
A *struct type member* has one of the following two forms:

. A *typed member*:
+
<<Lexical-Elements_Identifiers,_identifier_>> `:`
_[_
`[` <<Expressions,_expression_>> `]`
Expand All @@ -26,6 +28,15 @@ _[_
`format` <<Expressions_String-Literals,_string-literal_>>
_]_

. A *bit field member*:
+
<<Lexical-Elements_Identifiers,_identifier_>> `:`
( `signed` | `unsigned` )
<<Expressions,_expression_>>
_[_
`format` <<Expressions_String-Literals,_string-literal_>>
_]_

==== Semantics

The identifier is the name _N_ of the type.
Expand All @@ -34,7 +45,7 @@ The definition associates the name _N_ with a
of the specified type. Each
identifier appearing in the struct type member sequence must be distinct.

For each member _m_,
For each typed member _m_,

* The type name specifies the type stem:[T_m] of the member.

Expand All @@ -54,6 +65,47 @@ There is one argument to the format string, which is the member value.
If the size of the member is greater than one, then the
translator applies the format to each element.

For each bit field member _m_,

* The keyword `signed` or `unsigned` specifies the *signedness* of _m_.

* The expression following the keyword specifies the *bit width*
stem:[w_m] of _m_.
The expression must have a
<<Types_Internal-Types_Numeric-Types,numeric type>>, and it must
evaluate to a value stem:[w_m] after conversion to
<<Types_Internal-Types_Integer,_Integer_>>, with
stem:[1 <= w_m <= 64].

* The type stem:[T_m] of _m_ is the
<<Types_Primitive-Integer-Types,primitive integer type>>
with the specified signedness and with the smallest width
greater than or equal to stem:[w_m].
For example, the type of a member `unsigned 4` is `U8`, and
the type of a member `signed 12` is `I16`.
This type governs the use of the member in expressions and its
representation in generated code.

* The value stored in _m_ must be representable in stem:[w_m] bits:
in the range stem:[[0, 2^(w_m)-1\]] if _m_ is unsigned, and in the range
stem:[[-2^(w_m-1), 2^(w_m-1)-1\]] if _m_ is signed.
In particular, if the default value of the struct type specifies a
value for _m_, then the value must lie in this range.

* A bit field member represents a single value; it may not have a
size expression `[` _e_ `]`.

* The optional format specifier behaves as it does for a typed
member.

The bit width affects only the serialized form of the struct type,
not the in-memory representation.
Each maximal sequence of consecutive bit field members in the struct
type member sequence forms a *bit field group*.
The members of a bit field group are packed into a sequence of bytes
as described in the section on
<<Types_Serialized-Sizes,serialized sizes>>.

The expression following the keyword `default` is optional.
If present, it specifies the <<Types_Default-Values,default value>>
associated with the type.
Expand Down Expand Up @@ -97,4 +149,17 @@ struct C {
struct D {
x: [3] U32
} default { x = 1 }

# Defines a struct type E with two bit field members and one
# typed member.
# a and b form a bit field group of 12 bits, which is packed
# into 16 serialized bits (12 bits of data and 4 zero pad bits).
# The type of a is U8; the type of b is I16.
# The serialized size of E is 6 bytes: 2 bytes for the bit field
# group and 4 bytes for x.
struct E {
a: unsigned 3
b: signed 9
x: U32
}
----
2 changes: 2 additions & 0 deletions docs/spec/Lexical-Elements.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ serial
set
severity
signal
signed
size
sizeof
stack
Expand All @@ -140,6 +141,7 @@ topology
true
type
unmatched
unsigned
update
warning
with
Expand Down
27 changes: 25 additions & 2 deletions docs/spec/Types.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -297,14 +297,37 @@ representation type of _T_.

* If _T_ is a
<<Types_Struct-Types,struct type>>, then _s_
the sum of the serialized sizes of the members of _T_.
For each member _m_ with type stem:[T_m]:
the sum of the serialized sizes of the members of _T_
and of the
<<Definitions_Struct-Definitions,bit field groups>> of _T_,
in declaration order.
For each member _m_ with type stem:[T_m] that is not a bit field member:

** If _m_ has size _n_, then the serialized size of
_m_ is _n_ times the serialized size of stem:[T_m].

** Otherwise the serialized size of _m_ is the serialized size of stem:[T_m].

* Each bit field group _G_ of a struct type is serialized as a unit,
as follows:

** Let _w_ be the sum of the bit widths of the members of _G_.
The serialized size of _G_ is _w_ divided by 8, rounded up to the
nearest integer, in bytes.

** The members of _G_ are packed in declaration order into
the serialized bytes, from the most significant bit of the first
byte towards the least significant bit of the last byte,
with no intervening bits.
Each member occupies exactly its bit width, using the standard
binary representation of an unsigned integer or the two's complement
representation of a signed integer.

** If _w_ is not a multiple of 8, then the low-order bits of the
last byte that are not occupied by any member are *pad bits*.
Pad bits are zero in the serialized form and are ignored during
deserialization.

* If _T_ is an
<<Types_Alias-Types,alias type>>, then _s_ is the serialized size of the
<<Types_Underlying-Types,underlying type>> of _T_.
4 changes: 2 additions & 2 deletions editors/emacs/fpp-mode.el
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@
"locate" "low" "match" "on" "opcode" "orange"
"output" "param" "passive" "phase" "priority"
"queue" "queued" "raw" "recv" "red"
"ref" "reg" "resp" "save" "signal" "serial" "set" "severity"
"ref" "reg" "resp" "save" "signal" "signed" "serial" "set" "severity"
"size" "sizeof" "stack" "sync" "telemetry" "text" "throttle"
"time" "true" "unmatched" "update" "enter" "warning" "with"
"time" "true" "unmatched" "unsigned" "update" "enter" "warning" "with"
"yellow")
"All non-definition keywords for FPP.")

Expand Down
Loading