Macro-Based Register Config Helper

 

Code

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

// Define macros here
#define SET_ENABLE(x,val) \
( (val ? (x |= (0x1U << 0)) : (x &= (~(0x1U << 0)))) )

#define SET_MODE(x, val) \
do {\
    x &= (~(0x3U << 1)); \
    x |= ((val & 0x3U) << 1); \
} while (0)

#define SET_SPEED(x, val) \
do { \
    x &= (~(0x7U << 3)); \
    x |= ((val & 0x7U) << 3); \
} while (0)

#define SET_RESERVED(x) (x &= (~(0x3U << 6))) 

uint16_t build_register(uint8_t enable, uint8_t mode, uint8_t speed) {
    // Use macros to set fields
    uint16_t reg = 0;
    SET_ENABLE(reg, enable);
    SET_MODE(reg, mode);
    SET_SPEED(reg, speed);
    SET_RESERVED (reg);
    return reg;
}

int main() {
    uint8_t enable, mode, speed;
    scanf("%hhu %hhu %hhu", &enable, &mode, &speed);

    uint16_t reg = build_register(enable, mode, speed);
    printf("%u", reg);
    return 0;
}

Solving Approach

  1. To set one bit, since its either 0 or 1, we check the value of the user input, then set or clear the first bit of the register. If you dont want to use the ternary operator i.e (condition ? expression_if_true : expression_if_false;) you can use the do while syntax like:

    c
    #define SET_ENABLE(x, val) \
    do { \
    	if (val){ x |= (0x1U << 0); } \
    	else { x &= (~(0x1U << 0)); } \
    } while (0)
  2. To set the mode of register(x), which requires two bits. We use the value 3 dec as a mask since 3 dec in binary is 11, First step is to clear the two bits in position 1 & 2, this is done by left shifting the inverted mask (3) two times.

    x &= ( (~(0x3U)) << 1 )
  3. The next step is to now set the bits in position 1 & 2 using the val given by the user, we modify the mask by anding with the user input, then left shift it to bits 1 & 2.

    x |= ( (val & 0x3U) << 1 )
  4. To set the speed, we need to modify three bits, so our mask is 7 dec which is 111 in binary. The first step as usual is to clear the three bits of the register (x) from bit position 3 to 5:

    x &= ( (~(0x7U)) << 3 )
  5. The next step is to set the bit 3 to 5 of the register (x), first we AND it with the mask to change the mask to the user bits, then left shift to affect bits 3-5 only.

    x |= ( ((0x7U) & val) << 3)
  6. For the Reserved bits, they are two of them, So the mask becomes 3 dec == 11 binary.

    x &= ( (~(0x3U)) << 6 )
Upvote
Downvote
Loading...

Input

1 2 4

Expected Output

37