25. Pack Multiple Fields into a 16-bit Control Register

In embedded systems, multiple configuration fields are often packed into a single register using bit-level operations.

You are given the following field specifications to be packed into a 16-bit control register:

FieldBitsPosition (LSB-first)
Mode3Bits 0–2
Speed5Bits 3–7
Reserved2Bits 8–9 (must be 0)
Status6Bits 10–15

Your task is to:

  • Read mode, speed, and status from input
  • Pack them into a uint16_t register following the given bit layout
  • Ensure reserved bits (8–9) remain 0
  • Print the resulting packed value
     

Example-1

Input: mode = 3, speed = 10, status = 12
Output: 12371
(Hex: 0x3053, Binary: 0011000001010011)

Example-2

Input: mode = 7, speed = 31, status = 63
Output: 64767
(Hex: 0xFCFF, Binary: 1111110011111111)

Example-3

Input: mode = 4, speed = 16, status = 8
Output: 8324
(Hex: 0x2084, Binary: 0010000010000100)


 


 

Need Help? Refer to the Quick Guide below

In embedded systems, a single register often contains multiple fields, each controlling a different function. These fields are packed into specific bit positions.

Example: A 16-bit Control Register

BitsField Name
15 – 12Mode
11 – 8Speed
7 – 0Flags

To work with them, we need two core skills:

  1. Extracting a field (reading the bits at a specific position)
  2. Replacing or updating that field (without touching other bits)
     

This is done using bit masking and bit shifting.

To extract Speed field (bits 8 to 11):

uint16_t speed = (reg >> 8) & 0x0F;

To update the Mode field (bits 12 to 15):

reg &= ~(0x0F << 12);         // Clear Mode bits
reg |= ((new_mode & 0x0F) << 12); // Set new Mode

Key Operations

Extract a bit field

value = (reg >> position) & mask;

Replace a bit field

/* Where mask is a binary mask for the number of bits in the field.
E.g., For 3-bit field β†’ mask = 0x07 */


reg &= ~(mask << position);            // Clear the bits (mask= high bits)
reg |= ((new_value & mask) << position); // Set the new bits

Relevance in Embedded/Firmware

  • Most hardware registers (UART, Timer, ADC, SPI) use bit fields to define different parameters.
  • Peripheral setup often involves:
    • Extracting status bits (e.g., data ready, error)
    • Modifying specific bits (e.g., set baud rate, enable TX)
  • It’s unsafe to overwrite the entire register β€” instead, we update only the target bits.

This is why precise extraction and modification using bit masks is a core embedded skill.