Python library that provides classes for representing, defining and accessing registers in the embedded devices.
To add this library to your project do
uv add rgscore- To provide python API to define registers and serialize it into persistent json store/file.
- To provide access from Python to serialized form of register definitions (aka. addrMap json).
- Together with other libraries, such as i2c-api and i2c-drivers, to provide read and write access from Python to registers in live devices.
To fulfill above goals this library defines following classes
Register- defines/holds name, address, description, in-memory bitarray storage, reset value and a model of fields (list ofFieldDefobjects).FieldDef- holds register field definition which includes field name, bit-range in the larger register bitarray, numeric type, r/w flag, description and optional enum values that maps numeric value held in a register field to symbolic names.EnumValue- symbolic name corresponding to a numeric value in the field. Also includes description.RLink- abstract class that connects registers to physical hardware. Requires implementation that drives low level communication to live device.RLinkI2C- implementation ofRLinksuitable for linking classes in this library to physical devices over I2C bus.AddrMap- grouping of registers ensuring their uniqueness within addrMap. Primary class for (de)serialization to/from json file.
Registers are grouped into ordered collections known as addrMap's, represented by AddrMap class. When registers are
added to the addrMap this ensures that they are unique (both, with regard to register names and addresses) within a
given addrMap. Registers can be added to the addrMap at the time of construction or later by
calling AddrMap::add(...) method.
from rgscore import Register, AddrMap, FieldDef, EnumValue
addrMap = AddrMap(registers=[
Register(
bit_len=8,
name="Foo",
address=0x01,
desc="Register Foo",
model=[FieldDef.value_of("a@[3:0]U4.1#ro")]
)
])
addrMap.add(Register(
bit_len=8,
name="Bar",
address=0x02,
model=[
FieldDef.value_of("b@[3:0]U4.0#ro").with_description("field b").with_enum(
[EnumValue("START", 1, "Starting..."), EnumValue("STOP", 0, "Stoping...")]
)
],
))AddrMap ensures that registers do not have overlapping names or addresses.
Class Register holds
name- optional human-readable name.address- optional integer address within larger address space.desc- optional description.reset- reset value (default is 0x0)bit_len- bit width.address_bus_width_bytes- width of the address bus (default is 1).model- optional model of register fields, i.e. an array ofFieldDefinstances.link_provider- optional prover ofRLink, object that links this register to the physical hardware.
If model is None, then model with just one field spanning the whole of
the register width is autogenerated with numerical type of unsigned int.
When adding it to the AddrMap it must have an address. If name is not
present, then adding it to the AddrMap will autogenerate name in the
format R${hex_address}.
Class FieldDef can be created using string description by calling
FieldDef.value_of(...). Where description is
<field_name>@<bit_range><num_type>
or
<field_name>@<bit_range><num_type>#<rw_flag>
where <bit_range> is [<end_offset>,<start_offset>]
<num_type> is fixed point number definition in
simplified Q_(number_format), i.e. U or S (for unsigned or
signed) followed by bit-width, then dot, and then fraction.
Flag <rw_flag> is optional and can be "rw" (default) or "ro".
Description can be added by calling with_description(...) and enum values with_enum(...)
Instance of AddrMap can writen down into json file and read back like so
from pathlib import Path
from rgscore import AddrMap
addrMap = AddrMap(...)
# write into a file
addrMapFilePath = Path.home() / "addrMap.json"
addrMap.save_to_json_file(addrMapFilePath)
# load from a file
addrMap = AddrMap.new_instance_from_file(addrMapFilePath.read_text())AddrMap class can be instantiated with the URL that points to addrMap json file.
from rgscore import AddrMap
addrMap = AddrMap.new_instance_from_url("https://.../addrMap.json")By default, this will cache downloaded json file at $HOME/.rgscore/cache/
directory, so that subsequent calls to this function will load addrMap from
cache. Cache can be refreshed if force_reload=True argument is set.
To change cache location you can set RGSCORE_CACHE_DIR environment variable
to another folder.
To access physical hardware you need to create instance of RLink that
links AddrMap (and therefore registers) to live chip over some physical bus.
Below is an example of doing that over I2C bus. This requires you to bring in
two more libraries, i2c-api
and i2c-drivers.
from i2c_drivers import I2CMasterI2CDriver
from rgscore import AddrMap, RLinkI2C
regList = AddrMap.new_instance_from_file("regList-BMP581.json", link=RLinkI2C(I2CMasterI2CDriver(), 0x47))
odr_config = regList.get_register_by_name("ODR_CONFIG")
odr_config.read() # read from the chip at I2C address 0x47
print("pwr_mode", odr_config.get_field_value("pwr_mode"))
# set new pwr_mode and write this register to the chip
odr_config.set_field_value("pwr_mode", 1)
odr_config.write()