#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;
}
Input
3 10 12
Expected Output
12371