import board import busio import digitalio import microcontroller class IS31FL3733: def __init__(self, address=0x50): self.address = address self._page = None self._buffer = bytearray(12 * 16 + 1) self._buffer[0] = 0 self.pixels = memoryview(self._buffer)[1:] self.mode_mask = 0 self.power = digitalio.DigitalInOut(microcontroller.pin.P1_04) self.power.direction = digitalio.Direction.OUTPUT self.power.value = 1 # self.i2c = board.I2C() self.i2c = busio.I2C(board.SCL, board.SDA, frequency=400000) self.i2c.try_lock() # print(self.i2c.scan()) self.reset() self.setup() # print(self.open_pixels()) # print(self.short_pixels()) self.power.value = 0 def page(self, n): if self._page is n: return self._page = n self.write(0xFE, 0xC5) self.write(0xFD, n) def reset(self): # read reset register (0x11) of page 3 to reset self.page(3) self.read(0x11) def setup(self): # configure 3 breathing modes self.page(3) self.write(2, (2 << 5) | (0 << 1)) self.write(3, (2 << 5) | (3 << 1)) self.write(4, (0 << 4)) self.write(6, (2 << 5) | (0 << 1)) self.write(7, (2 << 5) | (2 << 1)) self.write(8, (0 << 4)) self.write(0xA, (1 << 5) | (0 << 1)) self.write(0xB, (1 << 5) | (1 << 1)) self.write(0xC, (0 << 4)) self.write(0, 1) self.write(0, 3) self.write(0xE, 0) self.set_brightness(128) self.page(0) self.write(0, [255] * 0x18) def set_brightness(self, n): n &= 0xFF self._brightness = n if not self.power.value: self.power.value = 1 # Global Current Control register (0x01) of page 3 self.page(3) self.write(1, n) @property def brightness(self): return self._brightness @brightness.setter def brightness(self, n): self.set_brightness(n) def clear(self): pixels = self.pixels for i in range(192): pixels[i] = 0 def pixel(self, i, r, g, b): """Set the pixel. It takes effect after calling update()""" row = i >> 4 # i // 16 col = i & 15 # i % 16 offset = row * 48 + col self.pixels[offset] = g self.pixels[offset + 16] = r self.pixels[offset + 32] = b def update_pixel(self, i, r, g, b): """Set the pixel and update""" row = i >> 4 # i // 16 col = i & 15 # i % 16 offset = row * 48 + col self.pixels[offset] = g self.pixels[offset + 16] = r self.pixels[offset + 32] = b self.power.value = 1 self.page(1) self.write(offset, g) self.write(offset + 16, r) self.write(offset + 32, b) if not self.any(): self.power.value = 0 def update(self): self.power.value = 1 self.page(1) self.i2c.writeto(self.address, self._buffer) if not self.any(): self.power.value = 0 def any(self): """Check if any pixel is not zero""" if self.mode_mask > 0: return True for pixel in self.pixels: if pixel > 0: return True return False def write(self, register, value): if type(value) is int: self.i2c.writeto(self.address, bytearray((register, value))) else: value.insert(0, register) buffer = bytearray(value) self.i2c.writeto(self.address, buffer) def read(self, register): buffer = bytearray(1) self.i2c.writeto_then_readfrom(self.address, bytearray((register,)), buffer) return buffer[0] def set_mode(self, i, mode=2): self.power.value = 1 self.page(2) row = i >> 4 # i // 16 col = i & 15 # i % 16 self.write(row * 48 + 32 + col, mode) # blue # self.write(row * 48 + col, mode) # green # self.write(row * 48 + 16 + col, mode) # red if mode: self.mode_mask |= 1 << i else: self.mode_mask &= ~(1 << i) if not self.any(): self.power.value = 0 def open_pixels(self): # 18h ~ 2Fh LED Open Register self.page(0) buffer = bytearray(0x18) self.i2c.writeto_then_readfrom(self.address, bytearray((0x18,)), buffer) return buffer def short_pixels(self): # 30h ~ 47h LED Short Register self.page(0) buffer = bytearray(0x18) self.i2c.writeto_then_readfrom(self.address, bytearray((0x30,)), buffer) return buffer