Skip to content

Commit bf6f229

Browse files
committed
docs/library: Document the new machine.I2CTarget class.
With some working examples that show how to use all the features. Signed-off-by: Damien George <[email protected]>
1 parent 277b615 commit bf6f229

File tree

2 files changed

+175
-0
lines changed

2 files changed

+175
-0
lines changed

docs/library/machine.I2CTarget.rst

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
.. currentmodule:: machine
2+
.. _machine.I2CTarget:
3+
4+
class I2CTarget -- an I2C target device
5+
=======================================
6+
7+
An I2C target is a device which connects to an I2C bus and is controlled by an
8+
I2C controller. I2C targets can take many forms. The :class:`machine.I2CTarget`
9+
class implements an I2C target that can be configured as a memory/register device,
10+
or as an arbitrary I2C device by using callbacks (if supported by the port).
11+
12+
Example usage for the case of a memory device::
13+
14+
from machine import I2CTarget
15+
16+
# Create the backing memory for the I2C target.
17+
mem = bytearray(8)
18+
19+
# Create an I2C target. Depending on the port, extra parameters
20+
# may be required to select the peripheral and/or pins to use.
21+
i2c = I2CTarget(addr=67, mem=mem)
22+
23+
# At this point an I2C controller can read and write `mem`.
24+
...
25+
26+
# Deinitialise the I2C target.
27+
i2c.deinit()
28+
29+
Note that some ports require an ``id``, and maybe ``scl`` and ``sda`` pins, to be
30+
passed to the `I2CTarget` constructor, to select the hardware I2C instance and
31+
pins that it connects to.
32+
33+
When configured as a memory device, it's also possible to register to receive events.
34+
For example to be notified when the memory is read/written::
35+
36+
from machine import I2CTarget
37+
38+
# Define an IRQ handler, for I2C events.
39+
def irq_handler(i2c_target):
40+
flags = i2c_target.irq().flags()
41+
if flags & I2CTarget.IRQ_END_READ:
42+
print("controller read target at addr", i2c_target.memaddr)
43+
if flags & I2CTarget.IRQ_END_WRITE:
44+
print("controller wrote target at addr", i2c_target.memaddr)
45+
46+
# Create the I2C target and register to receive default events.
47+
mem = bytearray(8)
48+
i2c = I2CTarget(addr=67, mem=mem)
49+
i2c.irq(irq_handler)
50+
51+
More complicated I2C devices can be implemented using the full set of events. For
52+
example, to see the raw events as they are triggered::
53+
54+
from machine import I2CTarget
55+
56+
# Define an IRQ handler that prints the event id and responds to reads/writes.
57+
def irq_handler(i2c_target, buf=bytearray(1)):
58+
flags = i2c_target.irq().flags()
59+
print(flags)
60+
if flags & I2CTarget.IRQ_READ_REQ:
61+
i2c_target.write(buf)
62+
if flags & I2CTarget.IRQ_WRITE_REQ:
63+
i2c_target.readinto(buf)
64+
65+
# Create the I2C target and register to receive all events.
66+
i2c = I2CTarget(addr=67)
67+
all_triggers = (
68+
I2CTarget.IRQ_ADDR_MATCH_READ
69+
| I2CTarget.IRQ_ADDR_MATCH_WRITE
70+
| I2CTarget.IRQ_READ_REQ
71+
| I2CTarget.IRQ_WRITE_REQ
72+
| I2CTarget.IRQ_END_READ
73+
| I2CTarget.IRQ_END_WRITE
74+
)
75+
i2c.irq(irq_handler, trigger=all_triggers, hard=True)
76+
77+
Constructors
78+
------------
79+
80+
.. class:: I2CTarget(id, addr, *, addrsize=7, mem=None, mem_addrsize=8, scl=None, sda=None)
81+
82+
Construct and return a new I2CTarget object using the following parameters:
83+
84+
- *id* identifies a particular I2C peripheral. Allowed values depend on the
85+
particular port/board. Some ports have a default in which case this parameter
86+
can be omitted.
87+
- *addr* is the I2C address of the target.
88+
- *addrsize* is the number of bits in the I2C target address. Valid values
89+
are 7 and 10.
90+
- *mem* is an object with the buffer protocol that is writable. If not
91+
specified then there is no backing memory and data must be read/written
92+
using the :meth:`I2CTarget.readinto` and :meth:`I2CTarget.write` methods.
93+
- *mem_addrsize* is the number of bits in the memory address. Valid values
94+
are 0, 8, 16, 24 and 32.
95+
- *scl* is a pin object specifying the pin to use for SCL.
96+
- *sda* is a pin object specifying the pin to use for SDA.
97+
98+
Note that some ports/boards will have default values of *scl* and *sda*
99+
that can be changed in this constructor. Others will have fixed values
100+
of *scl* and *sda* that cannot be changed.
101+
102+
General Methods
103+
---------------
104+
105+
.. method:: I2CTarget.deinit()
106+
107+
Deinitialise the I2C target. After this method is called the hardware will no
108+
longer respond to requests on the I2C bus, and no other methods can be called.
109+
110+
.. method:: I2CTarget.readinto(buf)
111+
112+
Read into the given buffer any pending bytes written by the I2C controller.
113+
Returns the number of bytes read.
114+
115+
.. method:: I2CTarget.write(buf)
116+
117+
Write out the bytes from the given buffer, to be passed to the I2C controller
118+
after it sends a read request. Returns the number of bytes written. Most ports
119+
only accept one byte at a time to this method.
120+
121+
.. method:: I2CTarget.irq(handler=None, trigger=IRQ_END_READ|IRQ_END_WRITE, hard=False)
122+
123+
Configure an IRQ *handler* to be called when an event occurs. The possible events are
124+
given by the following constants, which can be or'd together and passed to the *trigger*
125+
argument:
126+
127+
- ``IRQ_ADDR_MATCH_READ`` indicates that the target was addressed by a
128+
controller for a read transaction.
129+
- ``IRQ_ADDR_MATCH_READ`` indicates that the target was addressed by a
130+
controller for a write transaction.
131+
- ``IRQ_READ_REQ`` indicates that the controller is requesting data, and this
132+
request must be satisfied by calling `I2CTarget.write` with the data to be
133+
passed back to the controller.
134+
- ``IRQ_WRITE_REQ`` indicates that the controller has written data, and the
135+
data must be read by calling `I2CTarget.readinto`.
136+
- ``IRQ_END_READ`` indicates that the controller has finished a read transaction.
137+
- ``IRQ_END_WRITE`` indicates that the controller has finished a write transaction.
138+
139+
Not all triggers are available on all ports. If a port has the constant then that
140+
event is available.
141+
142+
Note the following restrictions:
143+
144+
- ``IRQ_ADDR_MATCH_READ``, ``IRQ_ADDR_MATCH_READ``, ``IRQ_READ_REQ`` and
145+
``IRQ_WRITE_REQ`` must be handled by a hard IRQ callback (with the *hard* argument
146+
set to ``True``). This is because these events have very strict timing requirements
147+
and must usually be satisfied synchronously with the hardware event.
148+
149+
- ``IRQ_END_READ`` and ``IRQ_END_WRITE`` may be handled by either a soft or hard
150+
IRQ callback (although note that all events must be registered with the same handler,
151+
so if any events need a hard callback then all events must be hard).
152+
153+
- If a memory buffer has been supplied in the constructor then ``IRQ_END_WRITE``
154+
is not emitted for the transaction that writes the memory address. This is to
155+
allow ``IRQ_END_READ`` and ``IRQ_END_WRITE`` to function correctly as soft IRQ
156+
callbacks, where the IRQ handler may be called quite some time after the actual
157+
hardware event.
158+
159+
.. attribute:: I2CTarget.memaddr
160+
161+
The integer value of the most recent memory address that was selected by the I2C
162+
controller (only valid if ``mem`` was specified in the constructor).
163+
164+
Constants
165+
---------
166+
167+
.. data:: I2CTarget.IRQ_ADDR_MATCH_READ
168+
I2CTarget.IRQ_ADDR_MATCH_WRITE
169+
I2CTarget.IRQ_READ_REQ
170+
I2CTarget.IRQ_WRITE_REQ
171+
I2CTarget.IRQ_END_READ
172+
I2CTarget.IRQ_END_WRITE
173+
174+
IRQ trigger sources.

docs/library/machine.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ Classes
264264
machine.UART.rst
265265
machine.SPI.rst
266266
machine.I2C.rst
267+
machine.I2CTarget.rst
267268
machine.I2S.rst
268269
machine.RTC.rst
269270
machine.Timer.rst

0 commit comments

Comments
 (0)