Açıklama Yok

k4be 85f720394d Make I2C bit timing cycle-exact for 400 kHz 3 gün önce
firmware 85f720394d Make I2C bit timing cycle-exact for 400 kHz 3 gün önce
host 85f720394d Make I2C bit timing cycle-exact for 400 kHz 3 gün önce
.gitignore 65e9d87ef9 Initial commit. Basic tests successful 3 gün önce
README.md 85f720394d Make I2C bit timing cycle-exact for 400 kHz 3 gün önce

README.md

USB-I2C bridge (ATmega8U2)

USB to I2C master for ATmega8U2. No LUFA, no interrupts: ~3.6 KB flash. Composite device with two independent ways in:

  • CDC-ACM virtual COM port with a fast batched binary protocol (below, host/usbi2c.py).
  • i2c-tiny-usb vendor interface (EP0 control requests only): the mainline Linux i2c-tiny-usb driver registers it as a normal kernel I2C adapter (/dev/i2c-N, i2c-tools, kernel client drivers).

  • Windows 10/11: binds inbox usbser.sys automatically (no driver/INF). Windows 7/8 need a stock CDC INF.

  • Windows: the vendor (i2c-tiny-usb) interface has no driver and shows up as an unknown device; harmless.

  • Linux: cdc_acm -> /dev/ttyACMx. Add the udev rule below so ModemManager does not probe it.

  • I2C is bit-banged (the 8U2 has no TWI): SCL=PD3, SDA=PD2, open drain. External pull-ups (2.2-4.7 k to 5 V) are required. Default 400 kHz (set_delay(0), the maximum); each step adds 0.375 us per SCL period (5 = 235 kHz, 10 = 163 kHz, 47 = 50 kHz). Timing is cycle-counted from the generated code: data bits meet Fast-mode tLOW >= 1.3 us and tHIGH >= 0.6 us, reads run at ~314 kHz.

  • Clock stretching supported; stuck-SDA bus recovery runs automatically before a transaction.

Build / flash (USBasp)

cd firmware
make
make fuses     # once: external crystal, CKDIV8 off (lfuse FF hfuse D9 efuse F4 - same as Arduino Uno 8U2)
make flash

Without the crystal fuse the chip runs from the 8 MHz/8 RC and USB will not enumerate. Flashing over ISP overwrites any DFU bootloader. Use make VBUS=1 if PB6 carries a VBUS sense (attach to USB only while PB6 high); not needed for a bus-powered board.

Protocol (binary, 0xA5-framed; frames may be concatenated)

Request Reply
A5 01 addr wlen rlen wdata.. (I2C xfer, 7-bit addr, <=32 B per phase; wlen&rlen>0 = repeated START; both 0 = probe) status [rdata]
A5 02 n set SCL delay status
A5 03 ping 00 proto maxlen
A5 04 bus recovery status

Status: 0 OK, 1 NACK addr, 2 NACK data, 3 bus error, 0x10 bad op, 0x11 bad length. Bytes outside a frame are ignored and a stalled frame is dropped after ~100 ms.

Speed: a USB bulk round trip is ~1 ms, so unbatched transactions are ~1000/s. Pipeline many frames in one write (Bridge.batch): the device answers a whole 64-byte OUT packet with one IN packet.

Host

pip install pyserial
python host/usbi2c.py COM5        # or /dev/ttyACM0 : scan, blink port 0, benchmark
from usbi2c import Bridge, TCA9539
io = TCA9539(Bridge("COM5"), 0x74)   # A1/A0 select 0x74..0x77
io.set_direction(0xFF00); io.write(0x00AA); print(hex(io.read()))

Linux udev (/etc/udev/rules.d/99-usbi2c.rules):

SUBSYSTEM=="tty", ATTRS{idVendor}=="1c40", ATTRS{idProduct}=="0534", ENV{ID_MM_DEVICE_IGNORE}="1", MODE="0666"
SUBSYSTEM=="i2c-dev", ATTRS{idVendor}=="1c40", ATTRS{idProduct}=="0534", MODE="0666"

VID/PID 1c40:0534 is the EZPrototypes i2c-tiny-usb ID, used so the stock kernel driver binds without changes. It is not ours: development use only, change it in usb.c for anything shipped (then bind with echo VID PID > /sys/bus/usb/drivers/i2c-tiny-usb/new_id).

Linux kernel I2C adapter (i2c-tiny-usb)

Kernel config: CONFIG_I2C_TINY_USB=m (Device Drivers > I2C > I2C Hardware Bus support > Tiny-USB adapter) and CONFIG_I2C_CHARDEV for /dev/i2c-N.

modprobe i2c-tiny-usb delay=1    # delay=N: SCL half period in us, rounded to the slower side
i2cdetect -l                     # "i2c-tiny-usb at bus 00X device 00Y"
i2cdetect -y N

delay: 0 or 1 = 400 kHz (the maximum), 2 = 235 kHz, 10 (driver default) = 50 kHz. It is sent when the driver binds. The kernel interface and the CDC set_delay command keep separate settings.

Kernel client drivers work too, e.g. TCA9539 (needs CONFIG_GPIOLIB + CONFIG_GPIO_PCA953X): echo tca9539 0x74 > /sys/bus/i2c/devices/i2c-N/new_device.

Notes:

  • cdc_acm keeps interfaces 0/1 (grouped by an IAD, which i2c-tiny-usb refuses); i2c-tiny-usb gets interface 2. Both can be used at the same time: while a kernel transaction is open (START sent, no STOP yet) CDC requests wait; an abandoned transaction is dropped after ~100 ms.
  • Each i2c_msg costs two control transfers, so a register read is ~4 ms. Use the CDC path for bulk work.
  • Address NAK -> -ENXIO; data NAK or bus error -> -EIO. No 10-bit addresses, no protocol mangling.