RFC: Hardware API: finalising machine.I2C
Posted: Fri Oct 21, 2016 7:17 am
Following from http://forum.micropython.org/viewtopic.php?f=3&t=2545, here we can discuss machine.I2C. This is really critical to get right, and make sure all ports implement it correctly, because it forms the basis of many drivers (eg LCD, env sensors, etc).
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:
Control/config methods:
Core transfer methods:
Composite helper methods for common transactions:
In addition to I2C there would be an I2CEndpoint class which is purely for convenience, but is probably going to be used much more than the low-level I2C class itself.
Endpoint constructor:
Endpoint attributes:
Endpoint methods:
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