add docstrings to bitbang
This commit is contained in:
parent
67e8d77421
commit
c64c89c652
|
@ -12,29 +12,41 @@ from litex.soc.interconnect.csr import *
|
|||
# I2C Master Bit-Banging ---------------------------------------------------------------------------
|
||||
|
||||
class I2CMaster(Module, AutoCSR):
|
||||
"""I2C Master Bit-Banging
|
||||
"""I2C bus master (bit-banged).
|
||||
|
||||
Provides the minimal hardware to do software I2C Master bit banging.
|
||||
This core provides minimal hardware for use as a software controlled bit-banged I2C bus master. I2C uses a
|
||||
tristate/open-drain output driver configuration with pull-up resistors, and this core expects that the pull-ups will
|
||||
be provided externally.
|
||||
|
||||
On the same write CSRStorage (_w), software can control:
|
||||
- SCL (I2C_SCL).
|
||||
- SDA direction and value (I2C_OE, I2C_W).
|
||||
Further information about the I2C bus can be found in the I2C standard document from NXP, `UM10204`_.
|
||||
|
||||
Software get back SDA value with the read CSRStatus (_r).
|
||||
.. _UM10204: https://www.pololu.com/file/0J435/UM10204.pdf
|
||||
"""
|
||||
pads_layout = [("scl", 1), ("sda", 1)]
|
||||
|
||||
def __init__(self, pads=None, default_dev=False):
|
||||
"""
|
||||
Class constructor.
|
||||
|
||||
:param pads: (optional) A ``Record`` object containing the pads ``scl`` and ``sda``.
|
||||
:param default_dev: (optional) A `bool` indicating whether this I2C master should be used as the default I2C
|
||||
interface (default is ``False``)
|
||||
"""
|
||||
self.init = []
|
||||
if pads is None:
|
||||
pads = Record(self.pads_layout)
|
||||
self.pads = pads
|
||||
self._w = CSRStorage(fields=[
|
||||
CSRField("scl", size=1, offset=0, reset=1),
|
||||
CSRField("oe", size=1, offset=1),
|
||||
CSRField("sda", size=1, offset=2, reset=1)],
|
||||
CSRField("scl", size=1, offset=0, reset=1, access=CSRAccess.WriteOnly,
|
||||
description="Drives the state of the SCL pad."),
|
||||
CSRField("oe", size=1, offset=1, access=CSRAccess.WriteOnly,
|
||||
description="Output Enable - if 0, both the SCL and SDA output drivers are disconnected."),
|
||||
CSRField("sda", size=1, offset=2, reset=1, access=CSRAccess.WriteOnly,
|
||||
description="Drives the state of the SDA pad.")],
|
||||
name="w")
|
||||
self._r = CSRStatus(fields=[
|
||||
CSRField("sda", size=1, offset=0)],
|
||||
CSRField("sda", size=1, offset=0, access=CSRAccess.ReadOnly,
|
||||
description="Contains the current state of the SDA pad.")],
|
||||
name="r")
|
||||
|
||||
self.default_dev = default_dev
|
||||
|
@ -42,6 +54,12 @@ class I2CMaster(Module, AutoCSR):
|
|||
self.connect(pads)
|
||||
|
||||
def connect(self, pads):
|
||||
"""
|
||||
Attaches the signals from inside the core to the input/output pads. This function is normally only called from
|
||||
inside the class constructor.
|
||||
|
||||
:param pads: A ``Record`` object containing the pads ``scl`` and ``sda``.
|
||||
"""
|
||||
# SCL
|
||||
self.specials += Tristate(pads.scl,
|
||||
o = 0, # I2C uses Pull-ups, only drive low.
|
||||
|
@ -55,12 +73,29 @@ class I2CMaster(Module, AutoCSR):
|
|||
)
|
||||
|
||||
def add_init(self, addr, init, init_addr_len=1):
|
||||
"""
|
||||
Adds an I2C write transaction that will be executed on startup. This method can be called multiple times to add
|
||||
multiple transactions that will be executed in order for this core instance.
|
||||
|
||||
:param addr: The I2C slave address to write to
|
||||
:param init: The bytes to write to the slave.
|
||||
:param init_addr_len: (optional) The init address length in bytes (default is 1)
|
||||
"""
|
||||
if init_addr_len not in (1, 2):
|
||||
raise ValueError("I2C slave addresses can only have a length of one or two bytes")
|
||||
|
||||
if init_addr_len == 1 and not 0 <= addr <= 127:
|
||||
raise ValueError("I2C slave address must be between 0 and 127 (inclusive)")
|
||||
elif init_addr_len == 2 and not 0 <= addr <= 1023:
|
||||
raise ValueError("I2C slave address must be between 0 and 1023 (inclusive)")
|
||||
|
||||
self.init.append((addr, init, init_addr_len))
|
||||
|
||||
class I2CMasterSim(I2CMaster):
|
||||
"""I2C Master Bit-Banging for Verilator simulation
|
||||
|
||||
Uses separate pads for SDA IN/OUT as Verilator does not support tristate pins well.
|
||||
class I2CMasterSim(I2CMaster):
|
||||
"""I2C bus master (bit-banged) for Verilator simulation
|
||||
|
||||
This core uses separate pads for SDA IN/OUT as Verilator does not support tristate pins well.
|
||||
"""
|
||||
pads_layout = [("scl", 1), ("sda_in", 1), ("sda_out", 1)]
|
||||
|
||||
|
@ -88,13 +123,23 @@ class I2CMasterSim(I2CMaster):
|
|||
# TODO: Find a more generic way to do it that would also apply to other peripherals?
|
||||
|
||||
def collect_i2c_info(soc):
|
||||
"""
|
||||
Collects all the I2C write transactions that have been added to run on startup for all ``I2CMaster`` instances
|
||||
into a single list. This information is used to generate C header files in ``litex.soc.integration.export``.
|
||||
|
||||
See ``I2CMaster.add_init`` for more information.
|
||||
|
||||
:param soc: ``SoCBase`` instance to scan for ``I2CMaster`` instances.
|
||||
:return: ``i2c_devs, i2c_init`` where ``i2c_devs`` is a list of all ``I2CMaster`` instances, and ``i2c_init`` is
|
||||
a list of tuples, where each tuple is (core instance name, slave address, bytes to write, slave address
|
||||
length in bytes)
|
||||
"""
|
||||
i2c_init = []
|
||||
i2c_devs = []
|
||||
for name, obj in xdir(soc, True):
|
||||
if isinstance(obj, I2CMaster):
|
||||
soc.add_config("HAS_I2C", check_duplicate=False)
|
||||
i2c_devs.append((name, getattr(obj, "default_dev")))
|
||||
if hasattr(obj, "init"):
|
||||
i2c_devs.append((name, obj.default_dev))
|
||||
for addr, init, init_addr_len in obj.init:
|
||||
i2c_init.append((name, addr, init, init_addr_len))
|
||||
return i2c_devs, i2c_init
|
||||
|
@ -102,30 +147,44 @@ def collect_i2c_info(soc):
|
|||
# SPI Master Bit-Banging ---------------------------------------------------------------------------
|
||||
|
||||
class SPIMaster(Module, AutoCSR):
|
||||
"""3/4-wire SPI Master Bit-Banging
|
||||
"""3/4-wire SPI bus master (bit-banged).
|
||||
|
||||
Provides the minimal hardware to do software 3/4-wire SPI Master bit banging.
|
||||
This core provides minimal hardware for use as a software controlled bit-banged SPI bus master.
|
||||
|
||||
On the same write CSRStorage (_w), software can control CLK (SPI_CLK), MOSI (SPI_MOSI), MOSI
|
||||
direction (SPI_OE) in the case 3-wire SPI and up to 4 Chip Selects (SPI_CS). Software get back
|
||||
MISO (SPI_MISO) with the read CSRStatus (_r).
|
||||
This core supports the typical SPI pads (MOSI, MISO, CLK) and a maximum of 4 CS outputs. If pull-up resistors are
|
||||
needed for 3 wire operation, they must be added externally.
|
||||
"""
|
||||
pads_layout = [("clk", 1), ("cs_n", 4), ("mosi", 1), ("miso", 1)]
|
||||
|
||||
def __init__(self, pads=None):
|
||||
"""
|
||||
Class constructor.
|
||||
|
||||
:param pads: (optional) A ``Record`` object containing: ``clk``, ``cs_n``, ``mosi`` and ``miso``.
|
||||
"""
|
||||
if pads is None:
|
||||
pads = Record(self.pads_layout)
|
||||
self.pads = pads
|
||||
assert len(pads.cs_n) <= 4
|
||||
|
||||
if len(pads.cs_n) > 4:
|
||||
raise ValueError("This core only supports a maximum of 4 CS outputs")
|
||||
|
||||
self._w = CSRStorage(fields=[
|
||||
CSRField("clk", size=1, offset=0),
|
||||
CSRField("mosi", size=1, offset=1),
|
||||
CSRField("oe", size=1, offset=2),
|
||||
CSRField("cs", size=1, offset=4)],
|
||||
name="w")
|
||||
CSRField("clk", size=1, offset=0, access=CSRAccess.WriteOnly,
|
||||
description="Drives the state of the CLK pad."),
|
||||
CSRField("mosi", size=1, offset=1, access=CSRAccess.WriteOnly,
|
||||
description="Drives the state of the MOSI pad."),
|
||||
CSRField("oe", size=1, offset=2, access=CSRAccess.WriteOnly,
|
||||
description="Output Enable for MOSI - if 0, the MOSI output driver is disconnected."),
|
||||
CSRField("cs", size=4, offset=4, access=CSRAccess.WriteOnly,
|
||||
description="Drives the state of the CS pads (up to 4, active high).")],
|
||||
name="w", description="SPI master output pad controls.")
|
||||
self._r = CSRStatus(fields=[
|
||||
CSRField("miso", size=1, offset=0),
|
||||
CSRField("mosi", size=1, offset=1)],
|
||||
name="r")
|
||||
CSRField("miso", size=1, offset=0, access=CSRAccess.ReadOnly,
|
||||
description="Contains the current state of the MISO pad."),
|
||||
CSRField("mosi", size=1, offset=1, access=CSRAccess.ReadOnly,
|
||||
description="Contains the current state of the MOSI pad.")],
|
||||
name="r", description="SPI master input pad states.")
|
||||
|
||||
# # #
|
||||
|
||||
|
|
Loading…
Reference in New Issue