#include #include #include #include // #define SET_BIT(BF, N) BF |= ((uint64_t)0x1 << N) // #define CLEAR_BIT(BF, N) BF &= ~((uint64_t)0x1 << N) // #define IS_BIT_SET(BF, N) ((BF >> N) & 0x1) // #define SET_BIT(BF, N) ((BF) |= ((typeof(BF))1 << (N))) // #define CLEAR_BIT(BF, N) ((BF) &= ~((typeof(BF))1 << (N))) // #define IS_BIT_SET(BF, N) (((BF) >> (N)) & (typeof(BF))1) #define UINT_CAST(x) \ _Generic((x), \ uint8_t: (uint8_t)1, \ uint16_t: (uint16_t)1, \ uint32_t: (uint32_t)1, \ uint64_t: (uint64_t)1, \ default: (x) /* fallback */ \ ) #define SET_BIT(BF, N) ((BF) |= (UINT_CAST(BF) << (N))) #define CLEAR_BIT(BF, N) ((BF) &= ~(UINT_CAST(BF) << (N))) #define IS_BIT_SET(BF, N) (((BF) >> (N)) & UINT_CAST(BF)) typedef enum : char { BRIGHTNESS_SET_INSTANT, //!< Set instantly with no delay BRIGHTNESS_CMD_TRY_SET, //!< Set brightness, ignored if setpoint already exists BRIGHTNESS_CMD_QUEUE, //!< Set brightness, queued if setpoint already exists BRIGHTNESS_CMD_FORCE, //!< Force set brightness target BRIGHTNESS_CMD_HOLD, //!< Force set brightness target to current brightness } brightness_cmd_t; typedef struct { uint8_t type : 8; uint32_t value : 24; } brightness_cmd; int main(void) { assert(sizeof(brightness_cmd) == 4); assert(sizeof(brightness_cmd_t) == 1); // Examples brightness_cmd cmd1 = {.type = BRIGHTNESS_CMD_FORCE, .value = 100}; brightness_cmd cmd2 = {.type = BRIGHTNESS_CMD_TRY_SET, .value = 50}; brightness_cmd cmd3 = {.type = BRIGHTNESS_CMD_QUEUE, .value = (1 << 23)}; // For readout comparisons later brightness_cmd read1 = cmd1; brightness_cmd read2 = cmd2; brightness_cmd read3 = cmd3; SET_BIT(*(int *)&read1, 10); // In this case, our command structure fits neatly into a 32 bit integer // so we can simply cast it directly: uint32_t int_cmd = *(uint32_t *)&cmd1; assert(memcmp(&int_cmd, &cmd1, 4) == 0); // To buffer char buf[12]; *(uint32_t *)&buf[0] = *(uint32_t *)&cmd1; *(uint32_t *)&buf[4] = *(uint32_t *)&cmd2; *(uint32_t *)&buf[8] = *(uint32_t *)&cmd3; // Wipe these so we can read them back from the buffer memset(&cmd1, 0, 4); memset(&cmd2, 0, 4); memset(&cmd3, 0, 4); // Note that these are neq's assert(memcmp(&cmd1, &read1, 4) != 0); assert(memcmp(&cmd2, &read2, 4) != 0); assert(memcmp(&cmd3, &read3, 4) != 0); cmd1 = *(brightness_cmd *)&buf[0]; cmd2 = *(brightness_cmd *)&buf[4]; cmd3 = *(brightness_cmd *)&buf[8]; assert(memcmp(&cmd1, &read1, 4) == 0); assert(memcmp(&cmd2, &read2, 4) == 0); assert(memcmp(&cmd3, &read3, 4) == 0); brightness_cmd casted = *(brightness_cmd *)&read1; assert(memcmp(&read1, &casted, 4) == 0); printf("Sizeof(brightness_cmd) = %ld\n", sizeof(brightness_cmd)); printf("Sizeof(brightness_cmd_t) = %ld\n", sizeof(brightness_cmd)); printf("All is well!\n"); }