Update 2026-09-15: most of this is done
Implemented for both machine.I2C and machine.SoftI2C: start(), stop(), write(buf),
readinto(buf, nack=1), writeto_mem(addr, memaddr, buf, *, addrsize=8),
readfrom_mem_into(addr, memaddr, buf, *, addrsize=8), plus a readfrom_mem(addr, memaddr, buf, n) caller-buffer extension. I2C already had writeto_mem/readfrom_mem ready-made in
the HAL; SoftI2C's equivalents are sequenced directly from start()/write()/read(),
which turned out to already be real HAL methods on both _I2C and _SoftI2C -- just never
wired to machine.py. SoftI2C.deinit() is a true no-op (bit-banged, nothing to release),
matching SoftSPI.deinit(). All of the above match the real stub except the trailing
positional-only /, so they're allowlisted at PyMCU/pymcu-micropython#12, not closed
outright.
Remaining, now precisely named:
Original report
MicroPython's machine.I2C/SoftI2C expose a lower-level primitive API (init, deinit,
start, stop, write, readinto) for manual bus sequencing, register-style helpers
(readfrom_mem, readfrom_mem_into, writeto_mem, writevto), and a target/slave mode
(machine.I2CTarget). None of it existed.
Repo choice
init()/deinit(): PyMCU/PyMCU#455 (and #453 for SoftI2C.init()). writevto/
I2CTarget: real, separate work, repo undetermined until scoped.
Update 2026-09-15: most of this is done
Implemented for both
machine.I2Candmachine.SoftI2C:start(),stop(),write(buf),readinto(buf, nack=1),writeto_mem(addr, memaddr, buf, *, addrsize=8),readfrom_mem_into(addr, memaddr, buf, *, addrsize=8), plus areadfrom_mem(addr, memaddr, buf, n)caller-buffer extension.I2Calready hadwriteto_mem/readfrom_memready-made inthe HAL;
SoftI2C's equivalents are sequenced directly fromstart()/write()/read(),which turned out to already be real HAL methods on both
_I2Cand_SoftI2C-- just neverwired to
machine.py.SoftI2C.deinit()is a true no-op (bit-banged, nothing to release),matching
SoftSPI.deinit(). All of the above match the real stub except the trailingpositional-only
/, so they're allowlisted atPyMCU/pymcu-micropython#12, not closedoutright.
Remaining, now precisely named:
I2C.init(freq=...)/.deinit()andSoftI2C.init(freq=...)-- need small HAL additions(
reinit()/deinit()onpymcu.hal.avr.i2c.I2C,set_freq()onpymcu.hal.softi2c.SoftI2C), named exactly at pymcu.hal.avr.i2c / softi2c need reinit/deinit (I2C) and set_freq (SoftI2C) PyMCU#455.SoftI2C.init()may alsoneed A Pin-typed field hides fields a match/case branch in __init__ assigns from later methods PyMCU#453 fixed first (a
Pin-typed field hides fields amatch/casebranchassigns -- the exact failure mode
SoftSPI.set_baudrate()already hit trying the samething).
I2C.writevto/SoftI2C.writevto(vectored write over a sequence of buffers in onetransaction) and
I2CTarget(slave mode, a dedicated ISR path) are real, separate piecesof work, not attempted here -- as this issue's own original text already said about
I2CTarget.Original report
MicroPython's
machine.I2C/SoftI2Cexpose a lower-level primitive API (init,deinit,start,stop,write,readinto) for manual bus sequencing, register-style helpers(
readfrom_mem,readfrom_mem_into,writeto_mem,writevto), and a target/slave mode(
machine.I2CTarget). None of it existed.Repo choice
init()/deinit(): PyMCU/PyMCU#455 (and #453 forSoftI2C.init()).writevto/I2CTarget: real, separate work, repo undetermined until scoped.