Microblaze Python Libraries

In addition to using the pynqmb libraries from C it is also possible to create Python wrappers for the libraries directly. PYNQ provides the MicroblazeLibrary class for this purpose.

The MicroblazeLibrary class takes a list of libraries as a construction parameter which should be the names of the header files desired without the .h file extension. All of the constants and functions will then become members of the instance of the class.

For this example we are going to interact with the Grove ADC device attached to a Pmod-Grove Adapter. We are going to want the i2c library for interacting with the device and the pmod_grove library to find the pins we want to connect to.


In [1]:
from pynq.overlays.base import BaseOverlay
from pynq.lib import MicroblazeLibrary

base = BaseOverlay('base.bit')
lib = MicroblazeLibrary(base.PMODA, ['i2c', 'pmod_grove'])


We can now inspect the lib to see all of the functions we can call and constants we have access.


In [2]:
dir(lib)


Out[2]:
['PMOD_G1_A',
 'PMOD_G1_B',
 'PMOD_G2_A',
 'PMOD_G2_B',
 'PMOD_G3_A',
 'PMOD_G3_B',
 'PMOD_G4_A',
 'PMOD_G4_B',
 '__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__init_subclass__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 '_build_constants',
 '_build_functions',
 '_mb',
 '_populate_typedefs',
 '_rpc_stream',
 'active_functions',
 'i2c_close',
 'i2c_get_num_devices',
 'i2c_open',
 'i2c_open_device',
 'i2c_read',
 'i2c_write',
 'release',
 'reset',
 'visitor']

Next we need to open our I2C device using the i2c_open function. This will return us an i2c object we can use for interacting with the bus.


In [3]:
device = lib.i2c_open(lib.PMOD_G4_B, lib.PMOD_G4_A)

We can check the functions we can call by using dir again.


In [4]:
dir(device)


Out[4]:
['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__index__',
 '__init__',
 '__init_subclass__',
 '__int__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 '_call_func',
 'close',
 'get_num_devices',
 'open',
 'open_device',
 'read',
 'val',
 'write']

The Grove ADC responds to address 0x50 and to read from it we need to write the register we want (0 for the result) and then read the two bytes back.


In [5]:
buf = bytearray(2)
buf[0] = 0
device.write(0x50, buf, 1)
device.read(0x50, buf, 2)

((buf[0] & 0x0F) << 8) | buf[1]


Out[5]:
831

This same approach can be used for all of the other libraries either included with PYNQ or from other sources.