Integer as Bit-Fields
Nothing here cannot be done via standard bit-manipulation (i.e. shifting and masking).
Built-in support is more elegant and performant since it usually replaces a sequence of multiple steps.
Since bit-wise operators are defined on integer numbers, individual bits can also be accessed and manipulated via an indexing syntax.
If a bit is set (i.e. 1
), the index access returns true
.
If a bit is not set (i.e. 0
), the index access returns false
.
When a range is used, the bits within the range are shifted and extracted as an integer value.
Bit-fields are very commonly used in embedded systems which must squeeze data into limited memory. Built-in support makes handling them efficient.
Indexing an integer as a bit-field is disabled for the no_index
feature.
Syntax
From Least-Significant Bit (LSB)
Bits in a bit-field are accessed with zero-based, non-negative integer indices:
integer
[
index from 0 to 63 or 31]
integer
[
index from 0 to 63 or 31] =
true
orfalse
;
Ranges can also be used:
integer
[
start..
end]
integer[
start..=
end]
integer
[
start..
end] =
new integer value ;
integer[
start..=
end] =
new integer value ;
The maximum bit number that can be accessed is 63 (or 31 under only_i32
).
Bits outside of the range are ignored.
From Most-Significant Bit (MSB)
A negative index accesses a bit in the bit-field counting from the end, or from the most-significant bit, with −1 being the highest bit.
integer
[
index from −1 to −64 or −32]
integer
[
index from −1 to −64 or −32] =
true
orfalse
;
Ranges always count from the least-significant bit (LSB) and has no support for negative positions.
The maximum bit number that can be accessed is −64 (or −32 under only_i32
).
Bit-Field Functions
The following standard functions (defined in the BitFieldPackage
but excluded
when using a raw Engine
) operate on INT
bit-fields.
These functions are available even under the no_index
feature.
Function | Parameter(s) | Description |
---|---|---|
get_bit | bit number, counting from MSB if < 0 | returns the state of a bit: true if 1 , false if 0 |
set_bit |
| sets the state of a bit |
get_bits |
| extracts a number of bits, shifted towards LSB |
get_bits | range of bits | extracts a number of bits, shifted towards LSB |
set_bits |
| sets a number of bits from the new value |
set_bits |
| sets a number of bits from the new value |
bits method and property |
| allows iteration over the bits of a bit-field |
bits | range of bits | allows iteration over the bits of a bit-field |
Example
// Assume the following bits fields in a single 16-bit word:
// ┌─────────┬────────────┬──────┬─────────┐
// │ 15-12 │ 11-4 │ 3 │ 2-0 │
// ├─────────┼────────────┼──────┼─────────┤
// │ 0 │ 0-255 data │ flag │ command │
// └─────────┴────────────┴──────┴─────────┘
let value = read_start_hw_register(42);
let command = value.get_bits(0, 3); // Command = bits 0-2
let flag = value[3]; // Flag = bit 3
let data = value[4..=11]; // Data = bits 4-11
let data = value.get_bits(4..=11); // <- above is the same as this
let reserved = value.get_bits(-4); // Reserved = last 4 bits
if reserved != 0 {
throw reserved;
}
switch command {
0 => print(`Data = ${data}`),
1 => value[4..=11] = data / 2,
2 => value[3] = !flag,
_ => print(`Unknown: ${command}`)
}