I need a bitfield definition that's compatible with ctypes Structures, so that I can use it as a pointer to a memory-mapped set of hardware registers, i.e.
class RegFile(Structure):
_fields_ = [
('ticks', c_uint32),
('id', id_bitfield),
]
Ideally they'd be very Pythonic things, and behave mostly like dicts. I've managed to work most of the gory details out to where I now have a factory function that makes bitfield classes similarly to making namedtuples. Here's an example of it ripping apart the fields of a standard float.
def make_register(name, fields, basetype=c_uint32):
# Define the underlying bitfield type
bitfield = type(name + '_bitfield', (LittleEndianStructure, ), {})
bitfield._pack_ = 1
bitfield._fields_ = fields
# Set up the union
d = {
'_fields_' : [('base', basetype), ('_b', bitfield)],
'_anonymous_' : ('_b',),
'__iter__' : _register_iter,
'keys' : _register_keys,
'items' : _register_items,
'update' : _register_update
}
return type(name, (Union, ), d)
ieee754_fields = [
('mantissa', c_uint, 23),
('exponent', c_uint, 8),
('sign', c_uint, 1)
]
IEEE754 = make_register('IEEE754', ieee754_fields, c_float)
x = IEEE754()
This works decently, but isn't a particularly Pythonic feeling syntax. Ideally I'd have some answer that allows me to define the bitfield class as:
class IEEE754(Register):
"""Individual bitfields of a standard IEEE-754 floating point number."""
_fields_ = ieee754_fields
_basetype_ = c_float
But I haven't been able to get that Register class to be a thing. It seemed like Register should inherit from Union and have some metaclass magic applied, but that way metaclass conflicts against Union lie. Any thoughts? Or should I just stick with what I've got?