def _parse_register(self, register_name: str, data: bytes) -> Union[str, dict]: """Parse individual register, returns wither one 32b value or dict of bitfields.""" register = {} bits = BitArray(data) # data is stored in little endian, but processed in big endian bits.byteswap() for field in self._get_bitfields(register_name, exclude_computed=False): width = parse_int(field.attrib["width"]) # exit early if we found a single 32b field if width == 32: return format_value(bits.uint, width) name = field.attrib["name"] offset = parse_int(field.attrib["offset"]) # OK, what the hell is that slicing about?! # offset is marked from the end of the bitarray not the begging like in a list # e.g.: ba = BitArray('0b00001100'), we want to extract bitfields of width=2 and offset=2 ('11') # again offset=2 means 2 bits from the end # BitArray supports negative indexing like an regular python list does: last bit has index -1 # that means we want to extract bits with indecies -4,-3 => [-4:-2] # HOWEVER: if we would want to extract 2 bits in the end (offset=0) # we would need to use [-offset:] slice or [-offset:None] slice_end = None if offset == 0 else -offset filed_bits = bits[-(offset + width): slice_end] register[name] = format_value(filed_bits.uint, width) return register
def _get_bitfield_config(self, register_name: str, exclude: bool) -> dict: """Get bitfield configuration.""" field_config = {} for field in self._get_bitfields(register_name, exclude): name = field.attrib["name"] value = format_value(int(field.attrib["reset_value"]), int(field.attrib["width"])) field_config[name] = value return field_config
def test_format_value(value, size, expected): assert format_value(value, size) == expected