Often bitwise operations are used instead of bitfield struct syntax but result code may be less readable opposite to original idea: bitfields. But there is simple solution to workaround weird syntax. Here you are:
#define __BITSTRUCT_MASK(LEN) ((1<<(LEN))-1)
#ifndef BITSTRUCT_GETBITS_IMPL
# define BITSTRUCT_GETBITS_IMPL(BS, OFFSET, LEN) \
(((BS)>>(OFFSET)) & __BITSTRUCT_MASK(LEN))
#endif
#ifndef BITSTRUCT_SETBITS_IMPL
# define BITSTRUCT_SETBITS_IMPL(BS, OFFSET, LEN, VALUE) \
((BS) & ~(__BITSTRUCT_MASK(LEN)<<(OFFSET)) | \
(((VALUE) & __BITSTRUCT_MASK(LEN))<<(OFFSET)))
#endif
#define BITSTRUCT enum
#define BITFIELD(NAME, OFFSET, LEN) NAME##_OFF = (OFFSET), NAME##_LEN=(LEN)
#define BITFIELD_MASK(NAME) __BITSTRUCT_MASK(NAME##_LEN)
#define BITFIELD_GET(NAME, BS) \
BITSTRUCT_GETBITS_IMPL(BS, NAME##_OFF, NAME##_LEN)
#define BITFIELD_SET(NAME, BS, VALUE) \
BITSTRUCT_SETBITS_IMPL(BS, NAME##_OFF, NAME##_LEN, VALUE)
So now it's possible to write something like this to describe register X:
|15.....8|7....4|3.....0| | ENABLE | FLAG | COUNT |
BITSTRUCT RegisterX {
// BITFIELD(NAME, OFFSET, LENGTH)
BITFIELD(RX_COUNT, 0, 4),
BITFIELD(RX_FLAG, 4, 4),
BITFIELD(RX_ENABLE, 8, 8)
};
int main(void)
{
int x = 0x1234; // raw value of register
// example of get/set field of bits' struct
x = BITFIELD_SET(RX_ENABLE, x, 0x98);
printf("%0X", BITFIELD_GET(RX_ENABLE, x));
return (0);
}
As you can see code is readable as in usual bitfield's struct, but instead of struct BITSTRUCT should be used,
and BITFIELD() descriptor instead of type NAME:len form. To set or to get field value, use BITFIELD_SET/GET() macros. BITFIELD_MASK() returns mask of field but from zero bit.But note the *_IMPL macros, using they, you can customize behavior of SET/GET implementation, for example to use some DSP core what can improve program performance dramatically! What you need is only to define own GET/SET helpers-implementators (BITSTRUCT_GETBITS_IMPL/BITSTRUCT_SETBITS_IMPL).