diff --git a/gex/__init__.py b/gex/__init__.py index 526049d..a055cbd 100644 --- a/gex/__init__.py +++ b/gex/__init__.py @@ -10,6 +10,7 @@ from gex.Client import Client from gex.units.DOut import DOut from gex.units.DIn import DIn from gex.units.Neopixel import Neopixel +from gex.units.I2C import I2C # General, low level diff --git a/gex/units/I2C.py b/gex/units/I2C.py new file mode 100644 index 0000000..8bd77d2 --- /dev/null +++ b/gex/units/I2C.py @@ -0,0 +1,72 @@ +import gex + +class I2C(gex.Unit): + """ + I2C master direct access + """ + + def _type(self): + return 'I2C' + + def _begin_i2c_pld(self, address:int, a10bit:bool=False): + pb = gex.PayloadBuilder() + if a10bit: address |= 0x8000 + pb.u16(address) + return pb + + def write(self, address:int, payload, a10bit:bool=False): + """ + Write to an address + """ + pb = self._begin_i2c_pld(address, a10bit) + pb.blob(payload) # payload to write + self.query(0x80, pb.close()) + + def read(self, address:int, count, a10bit:bool=False): + """ + Read from an address + """ + pb = self._begin_i2c_pld(address, a10bit) + pb.u16(count) # number of bytes to read + self.query(0x01, pb.close()) + + def read_reg(self, address:int, reg, width:int=1, a10bit:bool=False, endian='little'): + """ + Read a single register + """ + return self.read_regs(address, reg, count=1, width=width, a10bit=a10bit, endian=endian)[0] + + def read_regs(self, address:int, reg, count:int, width:int=1, a10bit:bool=False, endian='little'): + """ + Read multiple registers from an address + """ + pb = self._begin_i2c_pld(address, a10bit) + pb.u8(reg) + pb.u8(width*count) # we assume the device will auto-increment (most do) + resp = self.query(0x03, pb.close()) + + fields = [] + pp = gex.PayloadParser(resp.data, endian=endian) + for i in range(0, count): + if width==1: fields.append(pp.u8()) + elif width==2: fields.append(pp.u16()) + elif width==3: fields.append(pp.u24()) + elif width==4: fields.append(pp.u32()) + else: raise Exception("Bad width") + return fields + + def write_reg(self, address:int, reg, value:int, width:int=1, a10bit:bool=False, endian='little'): + """ + Write a to a single register + """ + pb = self._begin_i2c_pld(address, a10bit) + pb.u8(reg) + + pb.endian = endian + if width == 1: pb.u8(value) + elif width == 2: pb.u16(value) + elif width == 3: pb.u24(value) + elif width == 4: pb.u32(value) + else: raise Exception("Bad width") + + self.query(0x82, pb.close()) diff --git a/main.py b/main.py index ebef22b..f7d6a4b 100644 --- a/main.py +++ b/main.py @@ -50,14 +50,29 @@ if False: strip.write((b << 2) | ((~b) & 1)) time.sleep(.02) -if True: +if False: neo = gex.Neopixel(client, 'npx') print('We have %d neopixels.\n' % neo.get_len()) + #neo.load([0xF0F0F0,0,0,0xFF0000]) + # generate a little animation... for i in range(0,512): j = i if i < 256 else 255-(i-256) neo.load([0x660000+j, 0x3300FF-j, 0xFFFF00-(j<<8), 0x0000FF+(j<<8)-j]) - time.sleep(.005) + time.sleep(.001) + + neo.load([0,0,0,0]) + + +i2c = gex.I2C(client, 'i2c') + +# i2c.write(0x76, payload=[0xD0]) +# print(i2c.read(0x76, count=1)) + +print(i2c.read_reg(0x76, 0xD0)) +print("%x" % i2c.read_reg(0x76, 0xF9, width=3, endian='big')) +i2c.write_reg(0x76, 0xF4, 0xFA) +print(i2c.read_reg(0x76, 0xF4))