Extract Bit Field from 16-bit Register

Code

#include <stdio.h>
#include <stdint.h>

#define EXTRACT_START_POS   4U
#define EXTRACT_END_POS     8U

#define POS_MASK(val)       ((1 << (val + 1)) - 1)

// Define macros here
#define EXTRACT_DATA(val)   (val & (POS_MASK(EXTRACT_END_POS - EXTRACT_START_POS) << EXTRACT_START_POS))

uint8_t extract_field(uint16_t reg) 
{
    uint8_t extracted_data = (uint8_t)((EXTRACT_DATA(reg)) >> EXTRACT_START_POS);
    return extracted_data;
}

int main() 
{
    uint16_t reg;
    scanf("%hx", &reg);
    printf("%u", extract_field(reg));
    return 0;
}

Solving Approach

This program demonstrates a targeted Bit Field Extraction technique. It is designed to isolate and read a specific set of bits from a 16-bit register, a fundamental task in firmware development when parsing sensor data or hardware status flags.

1. Bit Field Specification

The code is configured to "cut out" a specific window from a uint16_t (2-byte) value:

  • Start Position: Bit 4

  • End Position: Bit 8

  • Field Width: 5 bits (Bits 4, 5, 6, 7, and 8)

  • Value Range: Can represent any integer from 0 to 31 ($2^5 - 1$).

2. Logical Breakdown

Step A: Creating a Relative Mask

The macro POS_MASK(EXTRACT_END_POS - EXTRACT_START_POS) calculates the width of the field. By subtracting the start from the end ($8 - 4 = 4$), it creates a 5-bit mask (binary 11111). This ensures the code only looks at a 5-bit wide window, regardless of where it is located in the register.

Step B: Alignment and Isolation (EXTRACT_DATA)

The 5-bit mask is shifted left by 4 positions (<< EXTRACT_START_POS) to align perfectly with the target bits in the register. A Bitwise AND (&) is then performed. This operation "blacks out" every bit in the register except for the data sitting in bits 4 through 8.

Step C: Normalization

The function extract_field takes the isolated bits and shifts them back to the right (>> EXTRACT_START_POS). This moves the data from its high-position "slot" down to the Least Significant Bit (LSB) position.

  • Example: If the raw bits at positions 4–8 represented the number 5, the shift converts the register value from 80 (binary ...01010000) to 5 (binary ...00000101).

3. Why This Approach is Used

  • Portability: By using EXTRACT_START_POS and EXTRACT_END_POS constants, the logic can be updated for different hardware registers by changing only two numbers.

  • Efficiency: The extraction happens using basic CPU instructions that execute in a single clock cycle, making it ideal for high-speed communication like SPI or CAN bus parsing.

  • Memory Safety: It returns a uint8_t, which is the smallest appropriate container for a 5-bit value, saving RAM in embedded systems.

Upvote
Downvote
Loading...

Input

0x01F0

Expected Output

31