From 80a49e70788d2849eeb83fba49756594000033e0 Mon Sep 17 00:00:00 2001 From: Jan Lindblom Date: Fri, 5 Aug 2022 21:26:39 +0300 Subject: [PATCH 1/3] Add support for LED matrices per layer. --- kmk/extensions/peg_rgb_matrix.py | 40 ++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/kmk/extensions/peg_rgb_matrix.py b/kmk/extensions/peg_rgb_matrix.py index 6bad5a02e..e76b9cfdb 100644 --- a/kmk/extensions/peg_rgb_matrix.py +++ b/kmk/extensions/peg_rgb_matrix.py @@ -1,3 +1,4 @@ +import gc import neopixel from storage import getmount @@ -37,6 +38,24 @@ def generate_led_map( keys = [key_color] * number_of_keys underglow = [underglow_color] * number_of_underglow print(f'Rgb_matrix_data(keys={keys},\nunderglow={underglow})') + return Rgb_matrix_data(keys, underglow) + + +class Rgb_matrix_layers: + def __init__(self, layers): + self.layers = layers if layers else [] + + @staticmethod + def generate_layer(number_of_leds, layer_color): + layers = [layer_color] * number_of_leds + print(f'Rgb_matrix_layers(layers={layers})') + + @staticmethod + def generate_layer(layer, ledDisplay): + return { + 0: layer, + 1: ledDisplay.data if type(ledDisplay) == Rgb_matrix_data else ledDisplay, + } class Rgb_matrix(Extension): @@ -53,12 +72,20 @@ def __init__( self.disable_auto_write = disable_auto_write self.split = split self.rightSide = rightSide + self.layerSensitiveLayers = False + self.layerLeds = None + self._prevLayers = 0 + if name.endswith('L'): self.rightSide = False elif name.endswith('R'): self.rightSide = True if type(ledDisplay) is Rgb_matrix_data: self.ledDisplay = ledDisplay.data + elif type(ledDisplay) is Rgb_matrix_layers: + self.layerSensitiveLayers = True + self.layerLeds = ledDisplay.layers + self.ledDisplay = self.layerLeds[0][1] # Default to first layer else: self.ledDisplay = ledDisplay @@ -105,6 +132,16 @@ def setBasedOffDisplay(self): for i, val in enumerate(self.ledDisplay): self.neopixel[self.keyPos[i]] = (val[0], val[1], val[2]) + def updateLEDs(self, active_layer): + if self.layerLeds != None: + for _, val in enumerate(self.layerLeds): + if val[0] == active_layer: + self.ledDisplay = val[1] + self.setBasedOffDisplay() + self.neopixel.show() + break + gc.collect() + def on_runtime_enable(self, sandbox): return @@ -125,6 +162,9 @@ def during_bootup(self, board): return def before_matrix_scan(self, sandbox): + if sandbox.active_layers[0] != self._prevLayers: + self._prevLayers = sandbox.active_layers[0] + self.updateLEDs(sandbox.active_layers[0]) return def after_matrix_scan(self, sandbox): From 8baa9b03f15cd6cc3ebbde8d3425395826e9aeae Mon Sep 17 00:00:00 2001 From: Jan Lindblom Date: Fri, 5 Aug 2022 21:42:39 +0300 Subject: [PATCH 2/3] Updating documentation. --- docs/peg_rgb_matrix.md | 109 ++++++++++++++++++++++++++--------------- 1 file changed, 69 insertions(+), 40 deletions(-) diff --git a/docs/peg_rgb_matrix.md b/docs/peg_rgb_matrix.md index c20061f91..52d49e5b0 100644 --- a/docs/peg_rgb_matrix.md +++ b/docs/peg_rgb_matrix.md @@ -1,44 +1,50 @@ # Peg RGB Matrix -### What you can and cannot do with this extension: +## What you can and cannot do with this extension: + +### Can Do -#### Can Do * Set any key's LED to be any color in a syntax very similar to your keymap * Allows specific keys to be set to OFF * Allows underglow LEDs to be a different color than per-key LEDs * Allows modifier keys to be set to a different color than alpha keys * Full split keyboard support +* Change LED color based on current layer +### Cannot Do (currently in progress) -#### Cannot Do (currently in progress) * Adjust color at runtime. Currently the extension requires changes to main.py in order to make changes to your LEDs. * Animations -* Change LED color based on current layer -### Keycodes +## Keycodes + Currently this extension does not support changing LEDs at runtime, as a result there is only a single keycode available to interact with this extension and that is KC.RGB_TOG. This keycode simply toggles all your LEDs on and off. ## Required Libraries + The following libraries must be frozen in your CircuitPython distribution or in a 'lib' folder at the root of your drive. + * [Adafruit_CircuitPython_NeoPixel](https://github.com/adafruit/Adafruit_CircuitPython_NeoPixel) * [Download .mpy versions from here](https://github.com/adafruit/Adafruit_CircuitPython_Bundle/releases/download/20220415/adafruit-circuitpython-bundle-7.x-mpy-20220415.zip) -# Required Changes to main.py and kb.py -In order to use this extension the user must make changes to both their kb.py and main.py files. Below you will find a more comprehensive list of changes required in order to use this extension. +## Required Changes to main.py and kb.py + +In order to use this extension the user must make changes to both their kb.py and main.py files. Below you will find a more comprehensive list of changes required in order to use this extension. + +### kb.py -## kb.py It is possible your chosen board may already have these changes made, if not you will need to make these additions: -The board's kb.py needs 3 fields: -* LED Key Position `led_key_pos` - * Much like `coord_mapping` this tells the extension where the LEDs are on your board. +The board's kb.py needs 3 fields: + +* LED Key Position `led_key_pos` + * Much like `coord_mapping` this tells the extension where the LEDs are on your board. * Brightness Limit `brightness_limit` - * Limits your brightness and may be required in order to stabilize performance. + * Limits your brightness and may be required in order to stabilize performance. * Number of LEDs `num_pixels` - * Used for calculations in order to ensure the LEDs map to the correct keys. - + * Used for calculations in order to ensure the LEDs map to the correct keys. -### Non-split Example: +#### Non-split Example: Below shows a simple non-split example for a board containing 48 LEDs total and 38 keys with per-key LEDs. This means we will have 10 underglow LEDs and 38 per-key LEDs. @@ -62,11 +68,10 @@ Underglow LEDs always appear at the end of the `led_key_pos` array, because the num_pixels = 48 ``` +#### Split Example: -### Split Example: - -Below shows a 58 key split keyboard's `led_key_pos` array for a board containing 70 LEDs in total. -The board has 58 keys, meaning we are left with 12 underglow LEDs total. +Below shows a 58 key split keyboard's `led_key_pos` array for a board containing 70 LEDs in total. +The board has 58 keys, meaning we are left with 12 underglow LEDs total. Since the board is a split and we can assume the LEDs are mirrored, that means each half has 29 per-key LEDs and 6 underglow LEDs. Let's first focus on the left half of the board. @@ -95,8 +100,8 @@ Underglow LEDs always appear at the end of the `led_key_pos` array, because the ``` +### main.py -## main.py It is possible your chosen board may already have these changes made, if not you will need to make these additions: ```python @@ -106,45 +111,49 @@ rgb_ext = Rgb_matrix(...per key color data) keyboard.extensions.append(rgb_ext) ``` -Rgb_matrix extension requires one argument (`Rgb_matrix_data`), although additional arguments can be passed, here are all arguments that can be passed to - -Rgb_matrix: +Rgb_matrix extension requires one argument (`Rgb_matrix_data`), although additional arguments can be passed, here are all arguments that can be passed to Rgb_matrix: * LED Display `ledDisplay` - * This is our primary and only required field, this takes a `Rgb_matrix_data` class. - * Rgb_matrix_data only takes two fields: - * Keys: an array of colors with a length equal to the number of keys on your keyboard - * Underglow: an array of colors with a length equal to the number of underglow leds on your keyboard + * This is our primary and only required field, this takes a `Rgb_matrix_data`, `Rgb_matrix_layers` or an array of LED colors. + * An array of LED color values should be the size of LEDs on the keyboard and follows the `led_key_pos` described above. + * `Rgb_matrix_data` only takes two fields: + * `keys`: an array of colors with a length equal to the number of keys on your keyboard + * `underglow`: an array of colors with a length equal to the number of underglow leds on your keyboard + * `Rgb_matrix_layers` only takes one field: + * Layers: an array of `{ 0: , 1: }` objects. These consists of an integer `layer` and an array `ledDisplay` with following the same syntax as the keys and underglow arrays described above. * Split `split` - * This is an optional boolean and only to be used if the keyboard is a split. + * This is an optional boolean and only to be used if the keyboard is a split. * Right Side `rightSide` - * This is optional boolean only to be used if the keyboard is split. This signals that this configuration is targetting the right side (off side). + * This is optional boolean only to be used if the keyboard is split. This signals that this configuration is targetting the right side (off side). * RGB Order `rgb_order` - * This is optional and only needs to be set if you are not using a WS2812 based LED. + * This is optional and only needs to be set if you are not using a WS2812 based LED. * Disable Auto Write `disable_auto_write` - * This is optional and only serves to make all your LEDs turn on at once instead of animate to their on state. + * This is optional and only serves to make all your LEDs turn on at once instead of animate to their on state. -### Colors -Colors are RGB and can be provided in one of two ways. +## Colors + +Colors are RGB and can be provided in one of two ways. Colors can be defined as an array of three numbers (0-255) or you can use the `Color` class with its default colors, see example below. ### Passing RGB Codes + ```python Rgb_matrix_data( keys=[[255,55,55],[55,55,55],[55,55,55],[55,55,55],[55,55,55],[55,55,55],"""... rest of colors""" ], underglow=[[0,0,55],[0,0,55],"""... rest of colors""" ] ) -``` +``` ### Using `Color` Class + ```python Rgb_matrix_data( keys=[Color.RED, Color.GREEN, Color.BLUE, Color.WHITE, Color.YELLOW, Color.ORANGE,"""... rest of colors""" ], underglow=[Color.PURPLE, Color.TEAL, Color.PINK, Color.OFF,"""... rest of colors""" ] ) -``` +``` -### Full Examples +## Full Examples ```python rgb_ext = Rgb_matrix(ledDisplay=Rgb_matrix_data( @@ -163,7 +172,27 @@ rgb_ext = Rgb_matrix(ledDisplay=Rgb_matrix_data( disable_auto_write=True) ``` -### Bonus +```python +rgb_ext = Rgb_matrix(ledDisplay=Rgb_matrix_layers( + layers=[ + { + 0: 0, + 1: [ + [255,55,55],[55,55,55],[55,55,55],[55,55,55],[55,55,55],[55,55,55], [55,55,55],[55,55,55],[55,55,55],[55,55,55],[55,55,55],[255,55,55], + [255,55,55],[55,55,55],[55,55,55],[55,55,55],[55,55,55],[55,55,55], [55,55,55],[55,55,55],[55,55,55],[55,55,55],[55,55,55],[255,55,55], + [255,55,55],[55,55,55],[55,55,55],[55,55,55],[55,55,55],[55,55,55], [55,55,55],[55,55,55],[55,55,55],[55,55,55],[55,55,55],[255,55,55], + [255,55,55],[55,55,55],[55,55,55],[55,55,55],[55,55,55],[55,55,55],[255,55,55],[255,55,55],[55,55,55],[55,55,55],[55,55,55],[55,55,55],[55,55,55],[255,55,55], + [255,55,55],[55,55,55],[55,55,55],[255,55,55],[255,55,55],[55,55,55],[55,55,55],[255,55,55], + [0,0,55],[0,0,55],[0,0,55],[0,0,55],[0,0,55],[0,0,55],[0,0,55],[0,0,55],[0,0,55],[0,0,55],[0,0,55],[0,0,55]], + }, + ]), + split=True, + rightSide=True, + disable_auto_write=True) +``` + +## Bonus + Because creating `ledDisplay` can be time consuming, there is a utility avaiable that will generate a basic framework for you. ```python @@ -173,7 +202,8 @@ Rgb_matrix_data.generate_led_map(58,10,Color.WHITE,Color.BLUE) Call `Rgb_matrix_data.generate_led_map` before you do any configuration beyond imports and it will print an `Rgb_matrix_data` class to your CircuitPython REPL which you can view by using a tool like "screen" or "PUTTY". Generate LED Map Arguments: -* Number of Keys + +* Number of Keys * Number of Underglow * Key Color * Underglow Color @@ -184,6 +214,5 @@ Example Using Above Arguments: Rgb_matrix_data(keys=[[249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249], [249, 249, 249]], underglow=[[0, 0, 255], [0, 0, 255], [0, 0, 255], [0, 0, 255], [0, 0, 255], [0, 0, 255], [0, 0, 255], [0, 0, 255], [0, 0, 255], [0, 0, 255]]) ``` -[Connecting to the Serial Console](https://learn.adafruit.com/welcome-to-circuitpython/kattni-connecting-to-the-serial-console) - +[Connecting to the Serial Console](https://learn.adafruit.com/welcome-to-circuitpython/kattni-connecting-to-the-serial-console) From 1f11eeabcb2169b76675147d6922d7d841435e93 Mon Sep 17 00:00:00 2001 From: Kyle Brown Date: Thu, 15 Sep 2022 20:36:58 -0700 Subject: [PATCH 3/3] Update kmk/extensions/peg_rgb_matrix.py --- kmk/extensions/peg_rgb_matrix.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmk/extensions/peg_rgb_matrix.py b/kmk/extensions/peg_rgb_matrix.py index e76b9cfdb..9e4047eba 100644 --- a/kmk/extensions/peg_rgb_matrix.py +++ b/kmk/extensions/peg_rgb_matrix.py @@ -133,7 +133,7 @@ def setBasedOffDisplay(self): self.neopixel[self.keyPos[i]] = (val[0], val[1], val[2]) def updateLEDs(self, active_layer): - if self.layerLeds != None: + if self.layerLeds is not None: for _, val in enumerate(self.layerLeds): if val[0] == active_layer: self.ledDisplay = val[1]