diff --git a/demo_dot_matrix_phat.py b/demo_dot_matrix_phat.py new file mode 100644 index 0000000..10eea18 --- /dev/null +++ b/demo_dot_matrix_phat.py @@ -0,0 +1,34 @@ +#!/bin/env python3 +import gex +import time + +ADDR = 0x61 +MODE = 0b00011000 +OPTS = 0b00001110 # 1110 = 35mA, 0000 = 40mA + +CMD_BRIGHTNESS = 0x19 +CMD_MODE = 0x00 +CMD_UPDATE = 0x0C +CMD_OPTIONS = 0x0D + +CMD_MATRIX_1 = 0x01 +CMD_MATRIX_2 = 0x0E + +with gex.Client(gex.TrxRawUSB()) as client: + bus = gex.I2C(client, 'i2c') + addr = 0x61 + bus.write_reg(addr, CMD_MODE, MODE) + bus.write_reg(addr, CMD_OPTIONS, OPTS) + bus.write_reg(addr, CMD_BRIGHTNESS, 64) + + bus.write(addr, [CMD_MATRIX_1, + 0xAA,0x55,0xAA,0x55, + 0xAA,0x55,0xAA,0x55, + ]) + + bus.write(addr, [CMD_MATRIX_2, + 0xFF, 0, 0xFF, 0, + 0xFF, 0, 0xFF, 0, + ]) + + bus.write_reg(addr, CMD_UPDATE, 0x01) \ No newline at end of file diff --git a/demo_dot_matrix_phat2.py b/demo_dot_matrix_phat2.py new file mode 100644 index 0000000..d21e747 --- /dev/null +++ b/demo_dot_matrix_phat2.py @@ -0,0 +1,200 @@ +#!/bin/env python3 +import random + +import gex +import time + +ADDR = 0x61 +MODE = 0b00011000 +OPTS = 0b00001110 # 1110 = 35mA, 0000 = 40mA + +CMD_BRIGHTNESS = 0x19 +CMD_MODE = 0x00 +CMD_UPDATE = 0x0C +CMD_OPTIONS = 0x0D + +CMD_MATRIX_1 = 0x01 +CMD_MATRIX_2 = 0x0E + +MATRIX_1 = 0 +MATRIX_2 = 1 + +# This is an adaptation of the phat library +# - the only change needed was replacing the smbus class with the GEX unit driver + +class NanoMatrix: + ''' + _BUF_MATRIX_1 = [ # Green +#Col 1 2 3 4 5 + 0b00000000, # Row 1 + 0b00000000, # Row 2 + 0b00000000, # Row 3 + 0b00000000, # Row 4 + 0b00000000, # Row 5 + 0b00000000, # Row 6 + 0b10000000, # Row 7, bit 8 = decimal place + 0b00000000 +] + _BUF_MATRIX_2 = [ # Red +#Row 8 7 6 5 4 3 2 1 + 0b01111111, # Col 1, bottom to top + 0b01111111, # Col 2 + 0b01111111, # Col 3 + 0b01111111, # Col 4 + 0b01111111, # Col 5 + 0b00000000, + 0b00000000, + 0b01000000 # bit 7, decimal place +] + _BUF_MATRIX_1 = [0] * 8 + _BUF_MATRIX_2 = [0] * 8 +''' + + def __init__(self, bus:gex.I2C, address=ADDR): + self.address = address + self._brightness = 127 + + self.bus = bus + + self.bus.write_byte_data(self.address, CMD_MODE, MODE) + self.bus.write_byte_data(self.address, CMD_OPTIONS, OPTS) + self.bus.write_byte_data(self.address, CMD_BRIGHTNESS, self._brightness) + + self._BUF_MATRIX_1 = [0] * 8 + self._BUF_MATRIX_2 = [0] * 8 + + def set_brightness(self, brightness): + self._brightness = int(brightness * 127) + if self._brightness > 127: self._brightness = 127 + + self.bus.write_byte_data(self.address, CMD_BRIGHTNESS, self._brightness) + + def set_decimal(self, m, c): + + if m == MATRIX_1: + if c == 1: + self._BUF_MATRIX_1[6] |= 0b10000000 + else: + self._BUF_MATRIX_1[6] &= 0b01111111 + + elif m == MATRIX_2: + + if c == 1: + self._BUF_MATRIX_2[7] |= 0b01000000 + else: + self._BUF_MATRIX_2[7] &= 0b10111111 + + #self.update() + + def set(self, m, data): + for y in range(7): + self.set_row(m, y, data[y]) + + def set_row(self, m, r, data): + for x in range(5): + self.set_pixel(m, x, r, (data & (1 << (4-x))) > 0) + + def set_col(self, m, c, data): + for y in range(7): + self.set_pixel(m, c, y, (data & (1 << y)) > 0) + + def set_pixel(self, m, x, y, c): + + if m == MATRIX_1: + if c == 1: + self._BUF_MATRIX_1[y] |= (0b1 << x) + else: + self._BUF_MATRIX_1[y] &= ~(0b1 << x) + elif m == MATRIX_2: + if c == 1: + self._BUF_MATRIX_2[x] |= (0b1 << y) + else: + self._BUF_MATRIX_2[x] &= ~(0b1 << y) + + #self.update() + + def clear(self, m): + if m == MATRIX_1: + self._BUF_MATRIX_1 = [0] * 8 + elif m == MATRIX_2: + self._BUF_MATRIX_2 = [0] * 8 + + self.update() + + def update(self): + for x in range(10): + try: + self.bus.write_i2c_block_data(self.address, CMD_MATRIX_1, self._BUF_MATRIX_1) + self.bus.write_i2c_block_data(self.address, CMD_MATRIX_2, self._BUF_MATRIX_2) + + self.bus.write_byte_data(self.address, CMD_UPDATE, 0x01) + break + except IOError: + print("IO Error") + + + + +with gex.Client(gex.TrxRawUSB()) as client: + bus = gex.I2C(client, 'i2c') + + n1 = NanoMatrix(bus, 0x61) + n2 = NanoMatrix(bus, 0x62) + n3 = NanoMatrix(bus, 0x63) + + n1.set_pixel(0, 0, 0, 1) + n1.set_pixel(0, 4, 0, 1) + n1.set_pixel(0, 0, 6, 1) + n1.set_pixel(0, 4, 6, 1) + + n1.set_pixel(1, 0, 0, 1) + n1.set_pixel(1, 4, 0, 1) + n1.set_pixel(1, 0, 3, 1) + n1.set_pixel(1, 4, 3, 1) + + n2.set_pixel(0, 0, 2, 1) + n2.set_pixel(0, 4, 2, 1) + n2.set_pixel(0, 0, 5, 1) + n2.set_pixel(0, 4, 5, 1) + + n2.set_pixel(1, 0, 0, 1) + n2.set_pixel(1, 4, 0, 1) + n2.set_pixel(1, 0, 6, 1) + n2.set_pixel(1, 4, 6, 1) + + + n3.set_pixel(0, 1, 0, 1) + n3.set_pixel(0, 3, 0, 1) + n3.set_pixel(0, 1, 6, 1) + n3.set_pixel(0, 3, 6, 1) + + n3.set_pixel(1, 1, 1, 1) + n3.set_pixel(1, 3, 1, 1) + n3.set_pixel(1, 1, 5, 1) + n3.set_pixel(1, 3, 5, 1) + + n1.update() + n2.update() + n3.update() + + b1 = 64 + b2 = 64 + b3 = 64 + + while True: + b1 += random.randint(-20, 15) + b2 += random.randint(-20, 15) + b3 += random.randint(-20, 15) + + if b1 < 0: b1 = 0 + if b2 < 0: b2 = 0 + if b3 < 0: b3 = 0 + if b1 > 127: b1 = 127 + if b2 > 127: b2 = 127 + if b3 > 127: b3 = 127 + + n1.set_brightness(b1) + n2.set_brightness(b2) + n3.set_brightness(b3) + + time.sleep(0.001) diff --git a/gex/units/I2C.py b/gex/units/I2C.py index 4e86580..8c3890f 100644 --- a/gex/units/I2C.py +++ b/gex/units/I2C.py @@ -47,26 +47,56 @@ class I2C(gex.Unit): 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") + if width==1: + for i in range(0, count): + fields.append(pp.u8()) + elif width==2: + for i in range(0, count): + fields.append(pp.u16()) + elif width==3: + for i in range(0, count): + fields.append(pp.u24()) + elif width==4: + for i in range(0, count): + 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', confirm=True): + def write_reg(self, address:int, reg, value, width:int=1, a10bit:bool=False, endian='little', confirm=True): """ - Write a to a single register + Write a to a single register. + value can be int or array (in which case `width` applies to each item) """ 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") + arr = value + if type(arr) is int: + arr = [value] + + if width == 1: + pb.blob(arr) + elif width == 2: + for v in arr: + pb.u16(v) + elif width == 3: + for v in arr: + pb.u24(v) + elif width == 4: + for v in arr: + pb.u32(v) + else: + raise Exception("Bad width") self._send(0x02, pb.close(), confirm=confirm) + + def write_byte_data(self, address, reg, value): + """ Compatibility alias for python3-smbus """ + return self.write_reg(address, reg, value) + + def write_i2c_block_data(self, address, reg, block): + """ Compatibility alias for python3-smbus """ + return self.write_reg(address, reg, block)