Pack Multiple Fields into a 16-bit Control Register

Code

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

#define FIELD_WIDTH(f) ((f).end_bit - (f).start_bit + 1)
#define SET_FIELD_WIDTH_16(width) (~(0xFFFF << (width)))
#define SET_BITS_TO_POSITON_16(reg, width, pos) ((SET_FIELD_WIDTH_16(width) & (reg)) << (pos))

uint16_t pack_register(uint8_t mode_p, uint8_t speed_p, uint8_t status_p) {
    typedef struct {
        const char name[10];
        const uint8_t start_bit;
        const uint8_t end_bit;
        uint8_t value;
    } RegisterField;

    RegisterField mode      = {"mode", 0, 2, mode_p};
    RegisterField speed     = {"speed", 3, 7, speed_p};
    RegisterField reserved  = {"reserved", 8, 9, 0};
    RegisterField status    = {"status", 10, 15, status_p};

    // Declare masks
    uint16_t mode_16, speed_16, status_16, reserved_16;

    // Apply field values to mask
    mode_16     = SET_BITS_TO_POSITON_16(mode.value, FIELD_WIDTH(mode), mode.start_bit);
    speed_16    = SET_BITS_TO_POSITON_16(speed.value, FIELD_WIDTH(speed), speed.start_bit);
    reserved_16 = SET_BITS_TO_POSITON_16(reserved.value, FIELD_WIDTH(reserved), reserved.start_bit);
    status_16   = SET_BITS_TO_POSITON_16(status.value, FIELD_WIDTH(status), status.start_bit);
    
    return (mode_16 | speed_16 | reserved_16 | status_16);
}

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

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

Solving Approach

 

 

 

Upvote
Downvote
Loading...

Input

3 10 12

Expected Output

12371