I think there should be a low-level I2C class which provides complete functionality and is relatively user-friendly, but at the same time being minimal. It should allow to construct I2C transactions piece-wise for cases where the data to send comes from different buffers (eg for controlling an LCD). It should allow to do (almost) everything without allocating on the heap.
Constructor:
Code: Select all
I2C(id, scl, sda, freq)
- id is the peripheral id, with -1 meaning software implementation
- scl, sda are pin objects
- freq is the frequency of the bus to use (could be called baudrate or baud)
Code: Select all
i2c.config(...) # general config function to get/set values, eg i2c.config(freq=100000)
i2c.close() # shut down the peripheral
Code: Select all
i2c.start(addr, dir) # dir is one of i2c.READ, i2c.WRITE
i2c.write(buf)
i2c.writebyte(int)
i2c.readinto(buf)
i2c.readbyte()
i2c.stop()
Code: Select all
i2c.writeto(addr, buf) # = start(addr, i2c.WRITE); write(buf); stop()
i2c.readfrom_into(addr, buf) # = start(addr, i2c.READ); readinto(buf); stop()
i2c.write_readinto(addr, wr_buf, rd_buf) # = start(addr, i2c.WRITE); write(wr_buf); start(addr, i2c.READ); readinto(buf); stop()
Endpoint constructor:
Code: Select all
I2CEndpoint(i2c, addr, regaddrsize=8)
- i2c is a bus
- addr is the device address
- regaddrsize is the number of bits (8/16/32) needed to specify an i2c register address
Code: Select all
ep.i2c # get the underlying i2c bus
ep.addr # get the device address
ep.regaddrsize # get the register address size
Code: Select all
ep.write(buf) # = i2c.writeto(ep.addr, buf)
ep.read(n) # = buf=bytearray(n); i2c.readfrom_into(ep.addr, buf); return buf
ep.readinto(buf) # = i2c.readfrom_into(ep.addr, buf)
ep.reg_write(regaddr, int_value) # select register and write value
ep.reg_read(regaddr) # select register and read value, returns an integer