Skip to content

Commit 2584fc8

Browse files
committed
ports: rpi pico - i2ctarget update transaction restart register mask
issue #: #9232 Signed-off-by: Andrew Mirsky <[email protected]>
1 parent a9d800b commit 2584fc8

File tree

2 files changed

+143
-142
lines changed

2 files changed

+143
-142
lines changed

ports/raspberrypi/common-hal/i2ctarget/I2CTarget.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ int common_hal_i2ctarget_i2c_target_is_addressed(i2ctarget_i2c_target_obj_t *sel
111111

112112
*address = self->peripheral->hw->sar;
113113
*is_read = !(self->peripheral->hw->raw_intr_stat & I2C_IC_INTR_STAT_R_RX_FULL_BITS);
114-
*is_restart = ((self->peripheral->hw->raw_intr_stat & I2C_IC_RAW_INTR_STAT_RD_REQ_RESET) != 0);
114+
*is_restart = ((self->peripheral->hw->raw_intr_stat & I2C_IC_INTR_STAT_R_RESTART_DET_BITS) != 0);
115115

116116
common_hal_i2ctarget_i2c_target_ack(self, true);
117117
return 1;

shared-bindings/i2ctarget/__init__.c

Lines changed: 142 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545
//|
4646
//| Example of emulating a simple device that can only handle single writes and reads::
4747
//|
48-
//|
4948
//| import board
5049
//| from i2ctarget import I2CTarget
5150
//|
@@ -56,7 +55,7 @@
5655
//| logger.setLevel(logging.INFO)
5756
//| logger.addHandler(NamedStreamHandler())
5857
//|
59-
//| logger.info("\n\ncode starting...")
58+
//| logger.info("\\n\\ncode starting...")
6059
//|
6160
//| # initialize an I2C target with a device address of 0x40
6261
//| with I2CTarget(board.SCL, board.SDA, (0x40,)) as device:
@@ -69,7 +68,7 @@
6968
//| # no request is pending
7069
//| continue
7170
//|
72-
//| # `with` invokes I2CTargetRequest's functions to handle the necessary opening and closing of a transaction
71+
//| # `with` invokes I2CTargetRequest's functions to handle the necessary opening and closing of a request
7372
//| with i2c_target_request:
7473
//|
7574
//| # the address associated with the request
@@ -87,144 +86,146 @@
8786
//| logger.info(f"write request to address 0x{address:02x}: {data}")
8887
//| # for our emulated device, writes have no effect
8988
//|
90-
//| This example sets up an I2C device that can be accessed via another device running circuitpython::
91-
//| import busio
92-
//| import board
93-
//| i2c = busio.I2C(board.SCL, board.SDA)
94-
//|
95-
//|
96-
//| # perform a single read
97-
//| while not i2c.try_lock():
98-
//| pass
99-
//| buffer = bytearray(1)
100-
//| i2c.readfrom_into(0x40, buffer)
101-
//| print(f"device responded with {buffer}")
102-
//| i2c.unlock()
103-
//|
104-
//| # perform a single write
105-
//| while not i2c.try_lock():
106-
//| pass
107-
//| buffer = bytearray(1)
108-
//| buffer[0] = 0x12
109-
//| i2c.writeto(0x40, buffer)
110-
//| print(f"wrote {buffer} to device")
111-
//| i2c.unlock()
112-
//|
113-
//| Typically, i2c devices support writes and reads to/from multiple register indices::
114-
//| import board
115-
//| from i2ctarget import I2CTarget
116-
//|
117-
//| import adafruit_logging as logging
118-
//| from logging import NamedStreamHandler
119-
//|
120-
//| logger = logging.getLogger('i2ctarget')
121-
//| logger.setLevel(logging.INFO)
122-
//| logger.addHandler(NamedStreamHandler())
123-
//|
124-
//| # emulate a target with 16 registers
125-
//| regs = [0] * 16
126-
//| register_index = None
127-
//|
128-
//| logger.info("\n\ncode starting...")
129-
//|
130-
//| # initialize an I2C target with a device address of 0x40
131-
//| with I2CTarget(board.SCL, board.SDA, (0x40,)) as device:
132-
//|
133-
//| while True:
134-
//| # check if there's a pending device request
135-
//| i2c_target_request = device.request()
136-
//|
137-
//| if not i2c_target_request:
138-
//| # no request is pending
139-
//| continue
140-
//|
141-
//| # work with the i2c request
142-
//| with i2c_target_request:
143-
//|
144-
//| if not i2c_target_request.is_read:
145-
//| # a write request
146-
//|
147-
//| # bytearray contains the request's first byte, the register's index
148-
//| index = i2c_target_request.read(1)[0]
149-
//|
150-
//| # bytearray containing the request's second byte, the data
151-
//| data = i2c_target_request.read(1)
152-
//|
153-
//| # if the request doesn't have a second byte, this is read transaction
154-
//| if not data:
155-
//|
156-
//| # since we're only emulating 16 registers, read from a larger address is an error
157-
//| if index > 15:
158-
//| logger.error(f"write portion of read transaction has invalid index {index}")
159-
//| continue
160-
//|
161-
//| logger.info(f"write portion of read transaction, set index to {index}'")
162-
//| register_index = index
163-
//| continue
164-
//|
165-
//| # since we're only emulating 16 registers, writing to a larger address is an error
166-
//| if index > 15:
167-
//| logger.error(f"write request to incorrect index {index}")
168-
//| continue
169-
//|
170-
//| logger.info(f"write request to index {index}: {data}")
171-
//| regs[index] = data[0]
172-
//| else:
173-
//| # our emulated device requires a read to be part of a full write-then-read transaction
174-
//| if not i2c_target_request.is_restart:
175-
//| logger.warning(f"read request without first writing is not supported")
176-
//| # still need to respond, but result data is not defined
177-
//| i2c_target_request.write(bytes([0xff]))
178-
//| register_index = None
179-
//| continue
180-
//|
181-
//| # the single read transaction case is covered above, so we should always have a valid index
182-
//| assert(register_index is not None)
183-
//|
184-
//| # the write-then-read to an invalid address is covered above,
185-
//| # but if this is a restarted read, index might be out of bounds so need to check
186-
//| if register_index > 16:
187-
//| logger.error(f"restarted read yielded an unsupported index")
188-
//| i2c_target_request.write(bytes([0xff]))
189-
//| register_index = None
190-
//| continue
191-
//|
192-
//| # retrieve the data from our register file and respond
193-
//| data = regs[register_index]
194-
//| logger.info(f"read request from index {register_index}: {data}")
195-
//| i2c_target_request.write(bytes([data]))
196-
//|
197-
//| # in our emulated device, a single read transaction is covered above
198-
//| # so any subsequent restarted read gets the value at the next index
199-
//| assert(i2c_target_request.is_restart is True)
200-
//| register_index += 1
201-
//|
202-
//| This second example creates I2C target device that can be accessed via another device running circuitpython::
203-
//| import busio
204-
//| import board
205-
//| i2c = busio.I2C(board.SCL, board.SDA)
206-
//|
207-
//| # perform a write transaction
208-
//| while not i2c.try_lock():
209-
//| pass
210-
//| buffer = bytearray(2)
211-
//| buffer[0] = 0x0b # the register index
212-
//| buffer[1] = 0xa1 # the value
213-
//| i2c.writeto(0x40, buffer)
214-
//| print(f"wrote {buffer} to device")
215-
//| i2c.unlock()
216-
//|
217-
//| # perform a full read transaction (write-then-read)
218-
//| while not i2c.try_lock():
219-
//| pass
220-
//| index_buffer = bytearray(1)
221-
//| index_buffer[0] = 0x0b
222-
//| read_buffer = bytearray(1)
223-
//| i2c.writeto_then_readfrom(0x40, index_buffer, read_buffer)
224-
//| print(f"read from device index {index_buffer}: {read_buffer}")
225-
//| i2c.unlock()
226-
//|
227-
//| Or accessed from Linux like this::
89+
//| This example creates an I2C target device that can be accessed via another device as an I2C controller::
90+
//|
91+
//| import busio
92+
//| import board
93+
//| i2c = busio.I2C(board.SCL, board.SDA)
94+
//|
95+
//| # perform a single read
96+
//| while not i2c.try_lock():
97+
//| pass
98+
//| buffer = bytearray(1)
99+
//| i2c.readfrom_into(0x40, buffer)
100+
//| print(f"device responded with {buffer}")
101+
//| i2c.unlock()
102+
//|
103+
//| # perform a single write
104+
//| while not i2c.try_lock():
105+
//| pass
106+
//| buffer = bytearray(1)
107+
//| buffer[0] = 0x12
108+
//| i2c.writeto(0x40, buffer)
109+
//| print(f"wrote {buffer} to device")
110+
//| i2c.unlock()
111+
//|
112+
//| Typically, i2c devices support writes and reads to/from multiple register indices as in this example ::
113+
//|
114+
//| import board
115+
//| from i2ctarget import I2CTarget
116+
//|
117+
//| import adafruit_logging as logging
118+
//| from logging import NamedStreamHandler
119+
//|
120+
//| logger = logging.getLogger('i2ctarget')
121+
//| logger.setLevel(logging.INFO)
122+
//| logger.addHandler(NamedStreamHandler())
123+
//|
124+
//| # emulate a target with 16 registers
125+
//| regs = [0] * 16
126+
//| register_index = None
127+
//|
128+
//| logger.info("\\n\\ncode starting...")
129+
//|
130+
//| # initialize an I2C target with a device address of 0x40
131+
//| with I2CTarget(board.SCL, board.SDA, (0x40,)) as device:
132+
//|
133+
//| while True:
134+
//| # check if there's a pending device request
135+
//| i2c_target_request = device.request()
136+
//|
137+
//| if not i2c_target_request:
138+
//| # no request is pending
139+
//| continue
140+
//|
141+
//| # work with the i2c request
142+
//| with i2c_target_request:
143+
//|
144+
//| if not i2c_target_request.is_read:
145+
//| # a write request
146+
//|
147+
//| # bytearray contains the request's first byte, the register's index
148+
//| index = i2c_target_request.read(1)[0]
149+
//|
150+
//| # bytearray containing the request's second byte, the data
151+
//| data = i2c_target_request.read(1)
152+
//|
153+
//| # if the request doesn't have a second byte, this is read transaction
154+
//| if not data:
155+
//|
156+
//| # since we're only emulating 16 registers, read from a larger address is an error
157+
//| if index > 15:
158+
//| logger.error(f"write portion of read transaction has invalid index {index}")
159+
//| continue
160+
//|
161+
//| logger.info(f"write portion of read transaction, set index to {index}'")
162+
//| register_index = index
163+
//| continue
164+
//|
165+
//| # since we're only emulating 16 registers, writing to a larger address is an error
166+
//| if index > 15:
167+
//| logger.error(f"write request to incorrect index {index}")
168+
//| continue
169+
//|
170+
//| logger.info(f"write request to index {index}: {data}")
171+
//| regs[index] = data[0]
172+
//| else:
173+
//| # our emulated device requires a read to be part of a full write-then-read transaction
174+
//| if not i2c_target_request.is_restart:
175+
//| logger.warning(f"read request without first writing is not supported")
176+
//| # still need to respond, but result data is not defined
177+
//| i2c_target_request.write(bytes([0xff]))
178+
//| register_index = None
179+
//| continue
180+
//|
181+
//| # the single read transaction case is covered above, so we should always have a valid index
182+
//| assert(register_index is not None)
183+
//|
184+
//| # the write-then-read to an invalid address is covered above,
185+
//| # but if this is a restarted read, index might be out of bounds so need to check
186+
//| if register_index > 16:
187+
//| logger.error(f"restarted read yielded an unsupported index")
188+
//| i2c_target_request.write(bytes([0xff]))
189+
//| register_index = None
190+
//| continue
191+
//|
192+
//| # retrieve the data from our register file and respond
193+
//| data = regs[register_index]
194+
//| logger.info(f"read request from index {register_index}: {data}")
195+
//| i2c_target_request.write(bytes([data]))
196+
//|
197+
//| # in our emulated device, a single read transaction is covered above
198+
//| # so any subsequent restarted read gets the value at the next index
199+
//| assert(i2c_target_request.is_restart is True)
200+
//| register_index += 1
201+
//|
202+
//| This second example creates I2C target device that can be accessed via another device as an I2C controller::
203+
//|
204+
//| import busio
205+
//| import board
206+
//| i2c = busio.I2C(board.SCL, board.SDA)
207+
//|
208+
//| # perform a write transaction
209+
//| while not i2c.try_lock():
210+
//| pass
211+
//| buffer = bytearray(2)
212+
//| buffer[0] = 0x0b # the register index
213+
//| buffer[1] = 0xa1 # the value
214+
//| i2c.writeto(0x40, buffer)
215+
//| print(f"wrote {buffer} to device")
216+
//| i2c.unlock()
217+
//|
218+
//| # perform a full read transaction (write-then-read)
219+
//| while not i2c.try_lock():
220+
//| pass
221+
//| index_buffer = bytearray(1)
222+
//| index_buffer[0] = 0x0b
223+
//| read_buffer = bytearray(1)
224+
//| i2c.writeto_then_readfrom(0x40, index_buffer, read_buffer)
225+
//| print(f"read from device index {index_buffer}: {read_buffer}")
226+
//| i2c.unlock()
227+
//|
228+
//| Or accessed from Linux like this::
228229
//|
229230
//| $ i2cget -y 1 0x40 0x0b
230231
//| 0xff

0 commit comments

Comments
 (0)