From def53fa1ce1ce4bc589a70e545c3407deeb1de2c Mon Sep 17 00:00:00 2001 From: Adam Reid Date: Sat, 2 Sep 2017 10:08:04 +0000 Subject: [PATCH 1/4] Added new mode to address 128 LED --- blinkstick/blinkstick.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/blinkstick/blinkstick.py b/blinkstick/blinkstick.py index 285a922..0775b15 100644 --- a/blinkstick/blinkstick.py +++ b/blinkstick/blinkstick.py @@ -208,15 +208,15 @@ def __init__(self, device=None, error_reporting=True): self.bs_serial = self.get_serial() - def _usb_get_string(self, device, index): + def _usb_get_string(self, device, length, index): try: - return usb.util.get_string(device, index) + return usb.util.get_string(device, length, index) except usb.USBError: # Could not communicate with BlinkStick device # attempt to find it again based on serial if self._refresh_device(): - return usb.util.get_string(self.device, index) + return usb.util.get_string(self.device, length, index) else: raise BlinkStickException("Could not communicate with BlinkStick {0} - it may have been removed".format(self.bs_serial)) @@ -269,7 +269,7 @@ def get_serial(self): if sys.platform == "win32": return self.device.serial_number else: - return self._usb_get_string(self.device, 3) + return self._usb_get_string(self.device, 256, 3) def get_manufacturer(self): """ @@ -281,7 +281,7 @@ def get_manufacturer(self): if sys.platform == "win32": return self.device.vendor_name else: - return self._usb_get_string(self.device, 1) + return self._usb_get_string(self.device, 256, 1) def get_description(self): @@ -294,7 +294,7 @@ def get_description(self): if sys.platform == "win32": return self.device.product_name else: - return self._usb_get_string(self.device, 2) + return self._usb_get_string(self.device, 256, 2) def set_error_reporting(self, error_reporting): """ @@ -350,7 +350,7 @@ def _determine_rgb(self, red=0, green=0, blue=0, name=None, hex=None): try: if name: # Special case for name="random" - if name == "random": + if name is "random": red = randint(0, 255) green = randint(0, 255) blue = randint(0, 255) @@ -417,8 +417,8 @@ def get_color(self, index=0, color_format='rgb'): raise BlinkStickException("Could not return current color in format %s" % color_format) def _determine_report_id(self, led_count): - report_id = 9 - max_leds = 64 + report_id = 10 + max_leds = 128 if led_count <= 8 * 3: max_leds = 8 @@ -432,6 +432,9 @@ def _determine_report_id(self, led_count): elif led_count <= 64 * 3: max_leds = 64 report_id = 9 + elif led_count <= 128 * 3: + max_leds = 128 + report_id = 10 return report_id, max_leds @@ -1527,7 +1530,7 @@ def find_by_serial(serial=None): else: for d in _find_blicksticks(): try: - if usb.util.get_string(d, 3) == serial: + if usb.util.get_string(d, 256, 3) == serial: devices = [d] break except Exception as e: From 767ff118a0000415bc30837eae1fdbe184346809 Mon Sep 17 00:00:00 2001 From: Adam Reid Date: Thu, 7 Sep 2017 07:55:02 +0000 Subject: [PATCH 2/4] Patched to work on Raspbian --- blinkstick/blinkstick.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/blinkstick/blinkstick.py b/blinkstick/blinkstick.py index 285a922..3f84cfb 100644 --- a/blinkstick/blinkstick.py +++ b/blinkstick/blinkstick.py @@ -208,15 +208,15 @@ def __init__(self, device=None, error_reporting=True): self.bs_serial = self.get_serial() - def _usb_get_string(self, device, index): + def _usb_get_string(self, device, length, index): try: - return usb.util.get_string(device, index) + return usb.util.get_string(device, length, index) except usb.USBError: # Could not communicate with BlinkStick device # attempt to find it again based on serial if self._refresh_device(): - return usb.util.get_string(self.device, index) + return usb.util.get_string(self.device, length, index) else: raise BlinkStickException("Could not communicate with BlinkStick {0} - it may have been removed".format(self.bs_serial)) @@ -269,7 +269,7 @@ def get_serial(self): if sys.platform == "win32": return self.device.serial_number else: - return self._usb_get_string(self.device, 3) + return self._usb_get_string(self.device, 256, 3) def get_manufacturer(self): """ @@ -281,7 +281,7 @@ def get_manufacturer(self): if sys.platform == "win32": return self.device.vendor_name else: - return self._usb_get_string(self.device, 1) + return self._usb_get_string(self.device, 256, 1) def get_description(self): @@ -294,7 +294,7 @@ def get_description(self): if sys.platform == "win32": return self.device.product_name else: - return self._usb_get_string(self.device, 2) + return self._usb_get_string(self.device, 256, 2) def set_error_reporting(self, error_reporting): """ @@ -350,7 +350,7 @@ def _determine_rgb(self, red=0, green=0, blue=0, name=None, hex=None): try: if name: # Special case for name="random" - if name == "random": + if name is "random": red = randint(0, 255) green = randint(0, 255) blue = randint(0, 255) @@ -1527,7 +1527,7 @@ def find_by_serial(serial=None): else: for d in _find_blicksticks(): try: - if usb.util.get_string(d, 3) == serial: + if usb.util.get_string(d, 256, 3) == serial: devices = [d] break except Exception as e: From afbd61202b0741fb829c808b2f0746a7e92e0b94 Mon Sep 17 00:00:00 2001 From: Adam Reid Date: Thu, 7 Sep 2017 09:01:25 +0000 Subject: [PATCH 3/4] Added 12bit color mode. Allows ATTiny85 to address twice as many LED with its limited memory --- blinkstick/blinkstick.py | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/blinkstick/blinkstick.py b/blinkstick/blinkstick.py index 3f84cfb..d16db80 100644 --- a/blinkstick/blinkstick.py +++ b/blinkstick/blinkstick.py @@ -188,6 +188,7 @@ class BlinkStick(object): inverse = False error_reporting = True max_rgb_value = 255 + mode = 0 def __init__(self, device=None, error_reporting=True): """ @@ -207,6 +208,7 @@ def __init__(self, device=None, error_reporting=True): self.open_device(device) self.bs_serial = self.get_serial() + self.mode = self.get_mode() def _usb_get_string(self, device, length, index): try: @@ -445,15 +447,23 @@ def set_led_data(self, channel, data): @param data: The LED data frame in GRB format """ - report_id, max_leds = self._determine_report_id(len(data)) - report = [0, channel] - for i in range(0, max_leds * 3): - if len(data) > i: - report.append(data[i]) - else: - report.append(0) + if self.mode == 3: + report_id, max_leds = self._determine_report_id(len(data)/2) + offset = max_leds * 3 + for i in range(0, offset): + d = data[i]>>4 + if len(data) > offset + i: + d += data[offset+i]&240 + report.append(d) + else: + report_id, max_leds = self._determine_report_id(len(data)) + for i in range(0, max_leds * 3): + if len(data) > i: + report.append(data[i]) + else: + report.append(0) self._usb_ctrl_transfer(0x20, 0x9, report_id, 0, bytes(bytearray(report))) @@ -491,6 +501,7 @@ def set_mode(self, mode): control_string = bytes(bytearray([4, mode])) self._usb_ctrl_transfer(0x20, 0x9, 0x0004, 0, control_string) + self.mode = mode def get_mode(self): """ From 195c67fbf3bb0e06be04402d61f6444f1e81b9e1 Mon Sep 17 00:00:00 2001 From: Adam Reid Date: Sat, 9 Sep 2017 09:05:10 +0000 Subject: [PATCH 4/4] Added method to control new frame repeat feature --- blinkstick/blinkstick.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/blinkstick/blinkstick.py b/blinkstick/blinkstick.py index 6d9195c..a5fca84 100644 --- a/blinkstick/blinkstick.py +++ b/blinkstick/blinkstick.py @@ -486,6 +486,16 @@ def get_led_data(self, count): return device_bytes[2: 2 + count * 3] + def set_repeat(self, repeat): + """ + Set the number of repeats on the frame + + @type repeat: int + @param mode: number of times to repeat the frame + """ + control_string = bytes(bytearray([20, repeat])) + self._usb_ctrl_transfer(0x20, 0x9, 0x14, 0, control_string) + def set_mode(self, mode): """ Set device mode for BlinkStick Pro. Device currently supports the following modes: