thunk / Rust for the Metal / Bits in Types

Bits in Types

M0 said the machine holds nothing but bytes, and that what a byte means depends on the agreement used to read it. A type is how Rust writes that agreement down. A type names a byte pattern: how many bytes, and how to read them. Once you see types that way, the low-level code ahead stops looking like magic and starts looking like labeled bytes.

The unsigned integers

The types you will meet most are the unsigned integers, and their names tell you their size:

The u means unsigned, no negative values, and the number is the count of bits. Eight bits, one byte; sixteen bits, two bytes; thirty-two bits, four.

Compound types are the same idea, continued. A struct is several named values laid out as bytes side by side. A struct holding a u16 and two u8s is, in memory, just those four bytes packed together (the compiler decides the exact arrangement). The type is the map that says which bytes are which.

One type you should meet early

Displays like the one this course drives use a 16-bit color format called RGB565: red, green, and blue packed into sixteen bits, so one whole color fits in a single u16. M4 takes it apart properly. For now, hold onto the size: one color, one u16, two bytes.

Splitting a u16

Here is the problem those two bytes create. M1 said the display is reached over SPI, and that wire carries one byte at a time. A u16 color is two bytes. To travel the wire, it must split into two u8s:

let c: u16 = 0x2A5B;         // two bytes: 0x2A high, 0x5B low
let high = (c >> 8) as u8;   // 0x2A
let low  = (c & 0xFF) as u8; // 0x5B

Two new tools here, both worth knowing cold.

c >> 8 is a shift. It slides every bit of c eight places to the right. The low byte falls off the end and is gone; the high byte slides down into the low position. What remains is the high byte, sitting where a single byte lives.

c & 0xFF is a mask. The & compares c bit by bit against 0xFF, which is eight 1s in the low byte and 0s above, and keeps only the bits where both have a 1. Everything above the low byte is zeroed. What remains is the low byte, untouched.

In both lines, as u8 then converts the u16 down to a u8, keeping the low byte, which is exactly the byte each expression arranged to put there.

That is the bridge to the next module. Buses carry bytes, one after another, and types tell you which bytes: how many, in what order, meaning what. M3 puts the bytes on the wire.

Key terms

Checks

Answer these to prove the lesson landed. Graded right here; nothing is sent anywhere.

What numbers can a u8 hold?

How many bytes is a u16?

An RGB565 color fits in which type?