i2ctarget – Two wire serial protocol target

The i2ctarget module contains classes to support an I2C target.

Example emulating a target with 2 addresses (read and write):

import board
from i2ctarget import I2CTarget

regs = [0] * 16
index = 0

with I2CTarget(board.SCL, board.SDA, (0x40, 0x41)) as device:
    while True:
        r = device.request()
        if not r:
            # Maybe do some housekeeping
        with r:  # Closes the transfer if necessary by sending a NACK or feeding dummy bytes
            if r.address == 0x40:
                if not r.is_read:  # Main write which is Selected read
                    b = r.read(1)
                    if not b or b[0] > 15:
                    index = b[0]
                    b = r.read(1)
                    if b:
                        regs[index] = b[0]
                elif r.is_restart:  # Combined transfer: This is the Main read message
                    n = r.write(bytes([regs[index]]))
                    # A read transfer is not supported in this example
                    # If the microcontroller tries, it will get 0xff byte(s) by the ctx manager (r.close())
            elif r.address == 0x41:
                if not r.is_read:
                    b = r.read(1)
                    if b and b[0] == 0xde:
                        # do something

This example sets up an I2C device that can be accessed from Linux like this:

$ i2cget -y 1 0x40 0x01
$ i2cset -y 1 0x40 0x01 0xaa
$ i2cget -y 1 0x40 0x01


I2CTarget makes use of clock stretching in order to slow down the host. Make sure the I2C host supports this.

Raspberry Pi in particular does not support this with its I2C hw block. This can be worked around by using the i2c-gpio bit banging driver. Since the RPi firmware uses the hw i2c, it’s not possible to emulate a HAT eeprom.

Available on these boards
  • AITHinker ESP32-C3S_Kit
  • AITHinker ESP32-C3S_Kit_2M
  • ATMegaZero ESP32-S2
  • Adafruit Camera
  • Adafruit EdgeBadge
  • Adafruit Feather ESP32 V2
  • Adafruit Feather ESP32-S2 TFT
  • Adafruit Feather ESP32-S3 TFT
  • Adafruit Feather ESP32S2
  • Adafruit Feather ESP32S3 4MB Flash 2MB PSRAM
  • Adafruit Feather ESP32S3 No PSRAM
  • Adafruit Feather HUZZAH32
  • Adafruit Feather M4 CAN
  • Adafruit Feather M4 Express
  • Adafruit Feather RP2040
  • Adafruit FunHouse
  • Adafruit Grand Central M4 Express
  • Adafruit Hallowing M4 Express
  • Adafruit ItsyBitsy M4 Express
  • Adafruit ItsyBitsy RP2040
  • Adafruit KB2040
  • Adafruit Macropad RP2040
  • Adafruit MagTag
  • Adafruit Matrix Portal M4
  • Adafruit Metro ESP32S2
  • Adafruit Metro M4 Airlift Lite
  • Adafruit Metro M4 Express
  • Adafruit Monster M4SK
  • Adafruit PyGamer
  • Adafruit PyPortal
  • Adafruit PyPortal Pynt
  • Adafruit PyPortal Titano
  • Adafruit Pybadge
  • Adafruit QT Py ESP32 PICO
  • Adafruit QT Py ESP32-S3 no psram
  • Adafruit QT Py ESP32C3
  • Adafruit QT Py ESP32S2
  • Adafruit QT Py RP2040
  • Adafruit QT2040 Trinkey
  • Adafruit Trellis M4 Express
  • AloriumTech Evo M51
  • Arduino Nano RP2040 Connect
  • Artisense Reference Design RD00
  • BBQ20KBD
  • BPI-Bit-S2
  • BPI-Leaf-S3
  • BastWiFi
  • Bee-Motion-S3
  • Bee-S3
  • CP32-M4
  • Challenger NB RP2040 WiFi
  • Challenger RP2040 LTE
  • Challenger RP2040 LoRa
  • Challenger RP2040 SubGHz
  • Challenger RP2040 WiFi
  • Challenger RP2040 WiFi/BLE
  • CircuitBrains Deluxe
  • CrumpS2
  • Cytron Maker Feather AIoT S3
  • Cytron Maker Nano RP2040
  • Cytron Maker Pi RP2040
  • DFRobot Beetle ESP32-C3
  • ESP 12k NodeMCU
  • ESP32-C3-DevKitM-1
  • ESP32-S2-DevKitC-1-N4
  • ESP32-S2-DevKitC-1-N4R2
  • ESP32-S3-Box-2.5
  • ESP32-S3-Box-Lite
  • ESP32-S3-DevKitC-1-N8
  • ESP32-S3-DevKitC-1-N8R2
  • ESP32-S3-DevKitC-1-N8R8
  • ESP32-S3-DevKitM-1-N8
  • ESP32-S3-EYE
  • ESP32-S3-USB-OTG-N8
  • Electrolama minik
  • EncoderPad RP2040
  • Espressif ESP32-EYE
  • Feather ESP32S2 without PSRAM
  • FeatherS2
  • FeatherS2 Neo
  • FeatherS2 PreRelease
  • FeatherS3
  • Fig Pi
  • Franzininho WIFI w/Wroom
  • Franzininho WIFI w/Wrover
  • Gravitech Cucumber M
  • Gravitech Cucumber MS
  • Gravitech Cucumber R
  • Gravitech Cucumber RS
  • HMI-DevKit-1.1
  • Hardkernel Odroid Go
  • HexKyS2
  • IoTs2
  • Kaluga 1
  • LILYGO TTGO T8 ESP32-S2 w/Display
  • LOLIN S3 16MB Flash 8MB PSRAM
  • MORPHEANS MorphESP-240
  • Melopero Shake RP2040
  • MicroDev microC3
  • MicroDev microS2
  • Mini SAM M4
  • MixGo CE
  • Oak Dev Tech BREAD2040
  • Oak Dev Tech Cast-Away RP2040
  • Oak Dev Tech PixelWing ESP32S2
  • Pimoroni Badger 2040
  • Pimoroni Interstate 75
  • Pimoroni Keybow 2040
  • Pimoroni Motor 2040
  • Pimoroni PGA2040
  • Pimoroni Pico LiPo (16MB)
  • Pimoroni Pico LiPo (4MB)
  • Pimoroni PicoSystem
  • Pimoroni Plasma 2040
  • Pimoroni Servo 2040
  • Pimoroni Tiny 2040 (2MB)
  • Pimoroni Tiny 2040 (8MB)
  • ProS3
  • PyCubedv04
  • PyCubedv04-MRAM
  • PyCubedv05
  • PyCubedv05-MRAM
  • PyKey 18 Numpad
  • PyKey 44 Ergo
  • PyKey 60
  • PyKey 87 TKL
  • RP2.65-F
  • RP2040 Stamp
  • Raspberry Pi Pico
  • Raspberry Pi Pico W
  • Robo HAT MM1 M4
  • S2Mini
  • S2Pico
  • SAM E54 Xplained Pro
  • SAM32v26
  • Saola 1 w/Wroom
  • Saola 1 w/Wrover
  • Seeed Studio XIAO ESP32C3
  • Seeeduino Wio Terminal
  • Seeeduino XIAO RP2040
  • Silicognition LLC M4-Shim
  • Silicognition LLC RP2040-Shim
  • SparkFun MicroMod RP2040 Processor
  • SparkFun MicroMod SAMD51 Processor
  • SparkFun Pro Micro RP2040
  • SparkFun Thing Plus - RP2040
  • SparkFun Thing Plus - SAMD51
  • Sprite_v2b
  • TG-Boards' Datalore IP M4
  • Targett Module Clip w/Wroom
  • Targett Module Clip w/Wrover
  • The Open Book Feather
  • TinyPICO
  • TinyPICO Nano
  • TinyS2
  • TinyS3
  • UARTLogger II
  • W5100S-EVB-Pico
  • W5500-EVB-Pico
  • Waveshare ESP32-S2-Pico
  • Waveshare ESP32-S2-Pico-LCD
  • Waveshare RP2040-Zero
  • WeAct Studio Pico
  • Wemos Lolin C3 Mini" // from Wemos MP
  • nanoESP32-S2 w/Wrover
  • nanoESP32-S2 w/Wroom
  • takayoshiotake Octave RP2040

class i2ctarget.I2CTarget(scl: microcontroller.Pin, sda: microcontroller.Pin, addresses: Sequence[int], smbus: bool = False)

Two wire serial protocol target

I2C is a two-wire protocol for communicating between devices. This implements the target (peripheral, sensor, secondary) side.

  • scl (Pin) – The clock pin

  • sda (Pin) – The data pin

  • addresses (list[int]) – The I2C addresses to respond to (how many is hardware dependent).

  • smbus (bool) – Use SMBUS timings if the hardware supports it

deinit() None

Releases control of the underlying hardware so other classes can use it.

__enter__() I2CTarget

No-op used in Context Managers.

__exit__() None

Automatically deinitializes the hardware on context exit. See Lifetime and ContextManagers for more info.

request(*, timeout: float = -1) I2CTargetRequest

Wait for an I2C request.


timeout (float) – Timeout in seconds. Zero means wait forever, a negative value means check once


I2CTargetRequest or None if timeout=-1 and there’s no request

Return type


class i2ctarget.I2CTargetRequest(target: I2CTarget, address: int, is_read: bool, is_restart: bool)

Information about an I2C transfer request This cannot be instantiated directly, but is returned by I2CTarget.request().

  • target – The I2CTarget object receiving this request

  • address – I2C address

  • is_read – True if the main target is requesting data

  • is_restart – Repeated Start Condition

address :int

The I2C address of the request.

is_read :bool

The I2C main controller is reading from this target.

is_restart :bool

Is Repeated Start Condition.

__enter__() I2CTargetRequest

No-op used in Context Managers.

__exit__() None

Close the request.

read(n: int = -1, ack: bool = True) bytearray

Read data. If ack=False, the caller is responsible for calling I2CTargetRequest.ack().

  • n – Number of bytes to read (negative means all)

  • ack – Whether or not to send an ACK after the n’th byte


Bytes read

write(buffer: circuitpython_typing.ReadableBuffer) int

Write the data contained in buffer.


buffer (ReadableBuffer) – Write out the data in this buffer


Number of bytes written

ack(ack: bool = True) None

Acknowledge or Not Acknowledge last byte received. Use together with I2CTargetRequest.read() ack=False.


ack – Whether to send an ACK or NACK