diff options
Diffstat (limited to 'docs/library')
| -rw-r--r-- | docs/library/machine.I2CTarget.rst | 174 | ||||
| -rw-r--r-- | docs/library/machine.rst | 1 |
2 files changed, 175 insertions, 0 deletions
diff --git a/docs/library/machine.I2CTarget.rst b/docs/library/machine.I2CTarget.rst new file mode 100644 index 000000000..0e4af84cb --- /dev/null +++ b/docs/library/machine.I2CTarget.rst @@ -0,0 +1,174 @@ +.. currentmodule:: machine +.. _machine.I2CTarget: + +class I2CTarget -- an I2C target device +======================================= + +An I2C target is a device which connects to an I2C bus and is controlled by an +I2C controller. I2C targets can take many forms. The :class:`machine.I2CTarget` +class implements an I2C target that can be configured as a memory/register device, +or as an arbitrary I2C device by using callbacks (if supported by the port). + +Example usage for the case of a memory device:: + + from machine import I2CTarget + + # Create the backing memory for the I2C target. + mem = bytearray(8) + + # Create an I2C target. Depending on the port, extra parameters + # may be required to select the peripheral and/or pins to use. + i2c = I2CTarget(addr=67, mem=mem) + + # At this point an I2C controller can read and write `mem`. + ... + + # Deinitialise the I2C target. + i2c.deinit() + +Note that some ports require an ``id``, and maybe ``scl`` and ``sda`` pins, to be +passed to the `I2CTarget` constructor, to select the hardware I2C instance and +pins that it connects to. + +When configured as a memory device, it's also possible to register to receive events. +For example to be notified when the memory is read/written:: + + from machine import I2CTarget + + # Define an IRQ handler, for I2C events. + def irq_handler(i2c_target): + flags = i2c_target.irq().flags() + if flags & I2CTarget.IRQ_END_READ: + print("controller read target at addr", i2c_target.memaddr) + if flags & I2CTarget.IRQ_END_WRITE: + print("controller wrote target at addr", i2c_target.memaddr) + + # Create the I2C target and register to receive default events. + mem = bytearray(8) + i2c = I2CTarget(addr=67, mem=mem) + i2c.irq(irq_handler) + +More complicated I2C devices can be implemented using the full set of events. For +example, to see the raw events as they are triggered:: + + from machine import I2CTarget + + # Define an IRQ handler that prints the event id and responds to reads/writes. + def irq_handler(i2c_target, buf=bytearray(1)): + flags = i2c_target.irq().flags() + print(flags) + if flags & I2CTarget.IRQ_READ_REQ: + i2c_target.write(buf) + if flags & I2CTarget.IRQ_WRITE_REQ: + i2c_target.readinto(buf) + + # Create the I2C target and register to receive all events. + i2c = I2CTarget(addr=67) + all_triggers = ( + I2CTarget.IRQ_ADDR_MATCH_READ + | I2CTarget.IRQ_ADDR_MATCH_WRITE + | I2CTarget.IRQ_READ_REQ + | I2CTarget.IRQ_WRITE_REQ + | I2CTarget.IRQ_END_READ + | I2CTarget.IRQ_END_WRITE + ) + i2c.irq(irq_handler, trigger=all_triggers, hard=True) + +Constructors +------------ + +.. class:: I2CTarget(id, addr, *, addrsize=7, mem=None, mem_addrsize=8, scl=None, sda=None) + + Construct and return a new I2CTarget object using the following parameters: + + - *id* identifies a particular I2C peripheral. Allowed values depend on the + particular port/board. Some ports have a default in which case this parameter + can be omitted. + - *addr* is the I2C address of the target. + - *addrsize* is the number of bits in the I2C target address. Valid values + are 7 and 10. + - *mem* is an object with the buffer protocol that is writable. If not + specified then there is no backing memory and data must be read/written + using the :meth:`I2CTarget.readinto` and :meth:`I2CTarget.write` methods. + - *mem_addrsize* is the number of bits in the memory address. Valid values + are 0, 8, 16, 24 and 32. + - *scl* is a pin object specifying the pin to use for SCL. + - *sda* is a pin object specifying the pin to use for SDA. + + Note that some ports/boards will have default values of *scl* and *sda* + that can be changed in this constructor. Others will have fixed values + of *scl* and *sda* that cannot be changed. + +General Methods +--------------- + +.. method:: I2CTarget.deinit() + + Deinitialise the I2C target. After this method is called the hardware will no + longer respond to requests on the I2C bus, and no other methods can be called. + +.. method:: I2CTarget.readinto(buf) + + Read into the given buffer any pending bytes written by the I2C controller. + Returns the number of bytes read. + +.. method:: I2CTarget.write(buf) + + Write out the bytes from the given buffer, to be passed to the I2C controller + after it sends a read request. Returns the number of bytes written. Most ports + only accept one byte at a time to this method. + +.. method:: I2CTarget.irq(handler=None, trigger=IRQ_END_READ|IRQ_END_WRITE, hard=False) + + Configure an IRQ *handler* to be called when an event occurs. The possible events are + given by the following constants, which can be or'd together and passed to the *trigger* + argument: + + - ``IRQ_ADDR_MATCH_READ`` indicates that the target was addressed by a + controller for a read transaction. + - ``IRQ_ADDR_MATCH_READ`` indicates that the target was addressed by a + controller for a write transaction. + - ``IRQ_READ_REQ`` indicates that the controller is requesting data, and this + request must be satisfied by calling `I2CTarget.write` with the data to be + passed back to the controller. + - ``IRQ_WRITE_REQ`` indicates that the controller has written data, and the + data must be read by calling `I2CTarget.readinto`. + - ``IRQ_END_READ`` indicates that the controller has finished a read transaction. + - ``IRQ_END_WRITE`` indicates that the controller has finished a write transaction. + + Not all triggers are available on all ports. If a port has the constant then that + event is available. + + Note the following restrictions: + + - ``IRQ_ADDR_MATCH_READ``, ``IRQ_ADDR_MATCH_READ``, ``IRQ_READ_REQ`` and + ``IRQ_WRITE_REQ`` must be handled by a hard IRQ callback (with the *hard* argument + set to ``True``). This is because these events have very strict timing requirements + and must usually be satisfied synchronously with the hardware event. + + - ``IRQ_END_READ`` and ``IRQ_END_WRITE`` may be handled by either a soft or hard + IRQ callback (although note that all events must be registered with the same handler, + so if any events need a hard callback then all events must be hard). + + - If a memory buffer has been supplied in the constructor then ``IRQ_END_WRITE`` + is not emitted for the transaction that writes the memory address. This is to + allow ``IRQ_END_READ`` and ``IRQ_END_WRITE`` to function correctly as soft IRQ + callbacks, where the IRQ handler may be called quite some time after the actual + hardware event. + +.. attribute:: I2CTarget.memaddr + + The integer value of the most recent memory address that was selected by the I2C + controller (only valid if ``mem`` was specified in the constructor). + +Constants +--------- + +.. data:: I2CTarget.IRQ_ADDR_MATCH_READ + I2CTarget.IRQ_ADDR_MATCH_WRITE + I2CTarget.IRQ_READ_REQ + I2CTarget.IRQ_WRITE_REQ + I2CTarget.IRQ_END_READ + I2CTarget.IRQ_END_WRITE + + IRQ trigger sources. diff --git a/docs/library/machine.rst b/docs/library/machine.rst index 76d111f11..3c22aa9af 100644 --- a/docs/library/machine.rst +++ b/docs/library/machine.rst @@ -264,6 +264,7 @@ Classes machine.UART.rst machine.SPI.rst machine.I2C.rst + machine.I2CTarget.rst machine.I2S.rst machine.RTC.rst machine.Timer.rst |
