Browse Source

Directly connected LED Matrix support.

This adds support for LEDs that are directly connected to the MCU, either in a matrix or to single pins.
skullY 6 years ago
parent
commit
f8896d8b92

+ 19 - 5
common_features.mk

@@ -116,7 +116,7 @@ ifeq ($(strip $(RGBLIGHT_ENABLE)), yes)
     endif
 endif
 
-VALID_MATRIX_TYPES := yes IS31FL3731 IS31FL3733 IS31FL3737 WS2812 custom
+VALID_MATRIX_TYPES := yes IS31FL3731 IS31FL3733 IS31FL3737 WS2812 custom pins pinmatrix
 
 LED_MATRIX_ENABLE ?= no
 ifneq ($(strip $(LED_MATRIX_ENABLE)), no)
@@ -129,6 +129,20 @@ ifneq ($(strip $(LED_MATRIX_ENABLE)), no)
     endif
 endif
 
+ifeq ($(strip $(LED_MATRIX_ENABLE)), pinmatrix)
+    CIE1931_CURVE = yes
+    OPT_DEFS += -DLED_MATRIX_PINMATRIX_ENABLE
+    COMMON_VPATH += $(DRIVER_PATH)/led
+    SRC += led_matrix_pinmatrix.c
+endif
+
+ifeq ($(strip $(LED_MATRIX_ENABLE)), pins)
+    CIE1931_CURVE = yes
+    OPT_DEFS += -DLED_MATRIX_PINS_ENABLE
+    COMMON_VPATH += $(DRIVER_PATH)/led
+    SRC += led_matrix_pins.c
+endif
+
 ifeq ($(strip $(LED_MATRIX_ENABLE)), IS31FL3731)
     OPT_DEFS += -DIS31FL3731
     COMMON_VPATH += $(DRIVER_PATH)/issi
@@ -150,7 +164,7 @@ endif
 endif
 
 ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes)
-	RGB_MATRIX_ENABLE = IS31FL3731
+    RGB_MATRIX_ENABLE = IS31FL3731
 endif
 
 ifeq ($(strip $(RGB_MATRIX_ENABLE)), IS31FL3731)
@@ -293,9 +307,9 @@ endif
 
 HAPTIC_ENABLE ?= no
 ifneq ($(strip $(HAPTIC_ENABLE)),no)
-	COMMON_VPATH += $(DRIVER_PATH)/haptic
-	SRC += haptic.c
-	OPT_DEFS += -DHAPTIC_ENABLE
+    COMMON_VPATH += $(DRIVER_PATH)/haptic
+    SRC += haptic.c
+    OPT_DEFS += -DHAPTIC_ENABLE
 endif
 
 ifneq ($(filter DRV2605L, $(HAPTIC_ENABLE)), )

+ 58 - 2
docs/feature_led_matrix.md

@@ -1,10 +1,66 @@
 # LED Matrix Lighting
 
-This feature allows you to use LED matrices driven by external drivers. It hooks into the backlight system so you can use the same keycodes as backlighting to control it.
+This feature allows you to use LED matrices driven by external drivers. It hooks into the [backlight subsystem](feature_backlight.md) so you can use the same keycodes as backlighting to control it. Many of the same configuration settings apply as well.
 
 If you want to use RGB LED's you should use the [RGB Matrix Subsystem](feature_rgb_matrix.md) instead.
 
-## Driver configuration
+LED Matrix supports LEDs that are connected directly to the MCU and LEDs connected to an external controller IC (such as the IS31FL3731 from ISSI.)
+
+## Directly Connected LEDs
+
+There are two ways that LEDs can be connected to the LED Matrix- 
+
+* Direct Pin: One pin per LED
+* Direct Pin Matrix: LED matrix with rows and columns
+
+### Direct Pin
+
+This driver uses LEDs that are connected directly to to a pin on the PCB. If you are not familiar with how to wire an LED directly to a microcontroller you can [follow this guide](https://create.arduino.cc/projecthub/rowan07/make-a-simple-led-circuit-ce8308). The process is similar for every microcontroller that QMK supports.
+
+You can configure the driver to either source or sink current, but that setting applies to all LEDs.
+
+Settings needed in `rules.mk`:
+
+| Variable | Description |
+|----------|-------------|
+| `BACKLIGHT_ENABLE = yes` | Turn on the backlight subsystem |
+| `LED_MATRIX_ENABLE = pins` | Enable the LED Matrix subsystem and configure it for directly connected LEDs |
+
+Settings needed in `config.h`:
+
+| Variable | Description | Default |
+|----------|-------------|---------|
+| `LED_MATRIX_PINS` | A list of pins with connected LEDs. | `{ }` |
+| `LED_DRIVER_LED_COUNT` | The number of LEDs connected to pins |
+
+### Direct Pin Matrix
+
+This driver supports driving an LED matrix that is connected directly to the local controller in a common-row cathode orientation. For more general information on LED matrices and how to design them there are several useful outside resources:
+
+* https://www.circuitspecialists.com/blog/build-8x8-led-matrix/
+* https://www.instructables.com/id/Make-Your-Own-LED-Matrix-/
+* https://appelsiini.net/2011/how-does-led-matrix-work/
+
+Settings needed in `rules.mk`:
+
+| Variable | Description |
+|----------|-------------|
+| `BACKLIGHT_ENABLE = yes` | Turn on the backlight subsystem |
+| `LED_MATRIX_ENABLE = pinmatrix` | Enable the LED Matrix subsystem and configure it for a matrix |
+
+Settings needed in `config.h`:
+
+| Variable | Description | Default |
+|----------|-------------|---------|
+| `LED_DRIVER_LED_COUNT` | (Required) How many LED lights are present | (none) |
+| `LED_MATRIX_COLS` | (Required) The number of columns (current sources) your matrix has | (none) |
+| `LED_MATRIX_COL_PINS` | (Required) A list of column pins, EG `{ B1, B2, B3, B4 }`| (none) |
+| `LED_MATRIX_ROWS` | (Required) The number of rows (current sinks) your matrix has | (none) |
+| `LED_MATRIX_ROW_PINS` | (Required) A list of row pins, EG `{ B5, B6, B7, B8 }` | (none) |
+
+## LED Driver ICs
+
+You can also use an LED driver chip. The IS31 series of ICs is popular and well supported in QMK.
 
 ### IS31FL3731
 

+ 103 - 0
drivers/led/led_matrix_pinmatrix.c

@@ -0,0 +1,103 @@
+/* Copyright 2017 Jason Williams
+ * Copyright 2018 Jack Humbert
+ * Copyright 2019 Clueboard
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef __AVR__
+#    include <avr/interrupt.h>
+#    include <avr/io.h>
+#    include <util/delay.h>
+#    define led_wait_us(us) wait_us(us)
+#else
+#    include "ch.h"
+#    include "hal.h"
+#    define led_wait_us(us) chSysPolledDelayX(US2RTC(STM32_SYSCLK, us))
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include "led_matrix_pinmatrix.h"
+#include "led_tables.h"
+#include "progmem.h"
+#include "quantum.h"
+#include "backlight.h"
+
+
+/*
+ * g_pwm_buffer is an array that represents the duty cycle (0-255) for each LED.
+ * FIXME: Map this from the wiring matrix to a physical location matrix at some point
+ */
+uint8_t g_pwm_buffer[LED_MATRIX_ROWS * LED_MATRIX_COLS];
+const pin_t led_row_pins[LED_MATRIX_ROWS] = LED_MATRIX_ROW_PINS;
+const pin_t led_col_pins[LED_MATRIX_COLS] = LED_MATRIX_COL_PINS;
+
+
+void led_matrix_pinmatrix_init_pins(void) {
+    /* Set all pins to output, we are not interested in reading any information.
+     */
+    for (uint8_t x = 0; x < LED_MATRIX_ROWS; x++) {
+        setPinOutput(led_row_pins[x]);
+        writePinLow(led_row_pins[x]);
+    }
+
+    for (uint8_t x = 0; x < LED_MATRIX_COLS; x++) {
+        setPinOutput(led_col_pins[x]);
+        writePinLow(led_col_pins[x]);
+    }
+}
+
+void led_matrix_pinmatrix_set_value(int index, uint8_t value) {
+    /* Set the brighness for a single LED.
+     */
+    if (index >= 0 && index < LED_DRIVER_LED_COUNT) {
+        g_pwm_buffer[index] = value;
+    }
+}
+
+void led_matrix_pinmatrix_set_value_all(uint8_t value) {
+    /* Set the brighness for all LEDs.
+     */
+    for (int i = 0; i < LED_DRIVER_LED_COUNT; i++) {
+        led_matrix_pinmatrix_set_value(i, value);
+    }
+}
+
+void led_matrix_pinmatrix_flush(void) {
+    /* This is a basic bit-banged pwm implementation.
+     */
+    uint8_t led_count = 0;
+    for (uint8_t row = 0; row < LED_MATRIX_ROWS; row++) {
+        writePinLow(led_row_pins[row]);
+        for (uint8_t col = 0; col < LED_MATRIX_COLS; col++) {
+            /* We spend ~128us on each LED, dividing that time between lit and unlit.
+             */
+            const uint8_t brightness = pgm_read_byte(&CIE1931_CURVE[g_pwm_buffer[led_count]]) / 2;
+            if (brightness > 0) {
+                writePinHigh(led_col_pins[col]);
+                for (int i = 0; i < 128; i++) {
+                    if (i == brightness) {
+                        writePinLow(led_col_pins[col]);
+                    }
+                    led_wait_us(1);
+                }
+            } else {
+                led_wait_us(128);
+            }
+            led_count++;
+        }
+    }
+}

+ 30 - 0
drivers/led/led_matrix_pinmatrix.h

@@ -0,0 +1,30 @@
+/* Copyright 2017 Jason Williams
+ * Copyright 2018 Jack Humbert
+ * Copyright 2019 Clueboard
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef LED_MATRIX_PINMATRIX_DRIVER_H
+#define LED_MATRIX_PINMATRIX_DRIVER_H
+
+void led_matrix_pinmatrix_init_pins(void);
+void led_matrix_pinmatrix_set_value(int index, uint8_t value);
+void led_matrix_pinmatrix_set_value_all(uint8_t value);
+void led_matrix_pinmatrix_flush(void);
+void led_matrix_pinmatrix_select_row(uint8_t row);
+void led_matrix_pinmatrix_unselect_row(uint8_t row);
+void led_matrix_pinmatrix_unselect_rows(void);
+
+#endif  // LED_MATRIX_PINMATRIX_DRIVER_H

+ 95 - 0
drivers/led/led_matrix_pins.c

@@ -0,0 +1,95 @@
+/* Copyright 2017 Jason Williams
+ * Copyright 2018 Jack Humbert
+ * Copyright 2019 Clueboard
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef __AVR__
+#    include <avr/interrupt.h>
+#    include <avr/io.h>
+#    include <util/delay.h>
+#    define led_wait_us(us) wait_us(us)
+#else
+#    include "ch.h"
+#    include "hal.h"
+#    define led_wait_us(us) chSysPolledDelayX(US2RTC(STM32_SYSCLK, us))
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include "led_matrix_pins.h"
+#include "led_tables.h"
+#include "progmem.h"
+#include "quantum.h"
+#include "backlight.h"
+
+
+/*
+ * g_pwm_buffer is an array that represents the duty cycle (0-255) for each LED.
+ */
+uint8_t g_pwm_buffer[LED_DRIVER_LED_COUNT];
+const pin_t led_pins[LED_DRIVER_LED_COUNT] = LED_MATRIX_PINS;
+
+#ifdef LED_MATRIX_PIN_SINK
+#    define led_pin_on(pin) writePinLow(pin)
+#    define led_pin_off(pin) writePinHigh(pin)
+#else
+#    define led_pin_on(pin) writePinHigh(pin)
+#    define led_pin_off(pin) writePinLow(pin)
+#endif
+
+void led_matrix_pins_init_pins(void) {
+    /* Set all pins to output, we are not interested in reading any information.
+     */
+    for (uint8_t x = 0; x < LED_DRIVER_LED_COUNT; x++) {
+        setPinOutput(led_pins[x]);
+        led_pin_off(led_pins[x]);
+    }
+}
+
+void led_matrix_pins_set_value(int index, uint8_t value) {
+    /* Set the brighness for a single LED.
+     */
+    if (index >= 0 && index < LED_DRIVER_LED_COUNT) {
+        g_pwm_buffer[index] = value;
+    }
+}
+
+void led_matrix_pins_set_value_all(uint8_t value) {
+    /* Set the brighness for all LEDs.
+     */
+    for (int i = 0; i < LED_DRIVER_LED_COUNT; i++) {
+        led_matrix_pins_set_value(i, value);
+    }
+}
+
+void led_matrix_pins_flush(void) {
+    /* This is a basic bit-banged pwm implementation.
+     */
+    for (uint8_t i = 0; i < LED_DRIVER_LED_COUNT; i++) {
+        /* We spend ~1.3ms on each LED, dividing that time between lit and unlit.
+         */
+        if (g_pwm_buffer[i] > 0) {
+            uint8_t brightness = pgm_read_byte(&CIE1931_CURVE[g_pwm_buffer[i]]) / 2;
+            led_pin_on(led_pins[i]);
+            led_wait_us(brightness);
+            led_pin_off(led_pins[i]);
+            led_wait_us(128 - brightness);
+        } else {
+            led_wait_us(128);
+        }
+    }
+}

+ 30 - 0
drivers/led/led_matrix_pins.h

@@ -0,0 +1,30 @@
+/* Copyright 2017 Jason Williams
+ * Copyright 2018 Jack Humbert
+ * Copyright 2019 Clueboard
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef LED_MATRIX_PINS_DRIVER_H
+#define LED_MATRIX_PINS_DRIVER_H
+
+void led_matrix_pins_init_pins(void);
+void led_matrix_pins_set_value(int index, uint8_t value);
+void led_matrix_pins_set_value_all(uint8_t value);
+void led_matrix_pins_flush(void);
+void led_matrix_pins_select_row(uint8_t row);
+void led_matrix_pins_unselect_row(uint8_t row);
+void led_matrix_pins_unselect_rows(void);
+
+#endif  // LED_MATRIX_PINS_DRIVER_H

+ 39 - 0
keyboards/1upkeyboards/sweet16/keymaps/tester/keymap.c

@@ -0,0 +1,39 @@
+#include QMK_KEYBOARD_H
+
+enum custom_keycodes {
+  UP_URL = SAFE_RANGE
+};
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+    LAYOUT_ortho_4x4(
+        KC_0,   KC_1,   KC_2,   KC_3,
+        KC_4,   KC_5,   KC_6,   KC_7,
+        KC_8,   KC_9,   KC_A,   KC_B,
+        KC_C,   RESET,  KC_E,   BL_STEP
+    )
+};
+
+bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+    switch (keycode) {
+        case UP_URL:
+            if (record->event.pressed) {
+                SEND_STRING("http://1upkeyboards.com");
+            }
+            return false;
+            break;
+    }
+    return true;
+}
+
+#ifdef ENCODER_ENABLE
+#include "encoder.h"
+void encoder_update_user(int8_t index, bool clockwise) {
+  if (index == 0) { /* First encoder */
+    if (clockwise) {
+      tap_code(KC_VOLU);
+    } else {
+      tap_code(KC_VOLD);
+    }
+  }
+}
+#endif

+ 0 - 1
keyboards/1upkeyboards/sweet16/sweet16.c

@@ -1 +0,0 @@
-#include "sweet16.h"

+ 0 - 30
keyboards/1upkeyboards/sweet16/sweet16.h

@@ -1,30 +0,0 @@
-#pragma once
-
-#include "quantum.h"
-
-// Any changes to the layout names and/or definitions must also be made to info.json
-
-#define LAYOUT_ortho_4x4( \
-    K00, K01, K02, K03, \
-    K10, K11, K12, K13, \
-    K20, K21, K22, K23, \
-    K30, K31, K32, K33  \
-) { \
-    { K00,   K01,   K02,   K03 }, \
-    { K10,   K11,   K12,   K13 }, \
-    { K20,   K21,   K22,   K23 }, \
-    { K30,   K31,   K32,   K33 }  \
-}
-
-#define LAYOUT_numpad_4x4( \
-    K00, K01, K02, K03, \
-    K10, K11, K12,      \
-    K20, K21, K22, K23, \
-       K31,   K32      \
-) { \
-    { K00,   K01,   K02,   K03 }, \
-    { K10,   K11,   K12,   KC_NO }, \
-    { K20,   K21,   K22,   K23 }, \
-    { KC_NO, K31,   K32,   KC_NO }  \
-}
-

+ 8 - 0
keyboards/1upkeyboards/sweet16/v2/promicro/config.h

@@ -17,6 +17,14 @@
 /* Set 0 if debouncing isn't needed */
 #define DEBOUNCE 5
 
+/* Backlight configuration
+ */
+#define LED_MATRIX_ROWS 4
+#define LED_MATRIX_ROW_PINS { B1, B3, B2, B4 }
+#define LED_MATRIX_COLS 4
+#define LED_MATRIX_COL_PINS { B6, D0, C6, D7 }
+#define LED_DRIVER_LED_COUNT 16
+
 /* Encoder pins */
 #define ENCODERS_PAD_A { F4 }
 #define ENCODERS_PAD_B { F5 }

+ 2 - 0
keyboards/1upkeyboards/sweet16/v2/promicro/rules.mk

@@ -3,6 +3,8 @@ BOOTLOADER = caterina
 LINK_TIME_OPTIMIZATION_ENABLE=yes
 
 ## Features
+BACKLIGHT_ENABLE = yes
+LED_MATRIX_ENABLE = pinmatrix
 CONSOLE_ENABLE = yes
 
 ## On a Pro Micro you have to choose between underglow and the rotary encoder.

+ 8 - 0
keyboards/1upkeyboards/sweet16/v2/proton_c/config.h

@@ -14,6 +14,14 @@
 /* COL2ROW or ROW2COL */
 #define DIODE_DIRECTION ROW2COL
 
+/* Backlight configuration
+ */
+#define LED_MATRIX_ROWS 4
+#define LED_MATRIX_ROW_PINS { B13, B14, B15, B1 }
+#define LED_MATRIX_COLS 4
+#define LED_MATRIX_COL_PINS { B9, B6, B4, B3 }
+#define LED_DRIVER_LED_COUNT 16
+
 /* Encoder pins */
 #define ENCODERS_PAD_A { A2 }
 #define ENCODERS_PAD_B { A1 }

+ 2 - 0
keyboards/1upkeyboards/sweet16/v2/proton_c/rules.mk

@@ -2,5 +2,7 @@ MCU = STM32F303
 
 ## Features
 CONSOLE_ENABLE = yes
+BACKLIGHT_ENABLE = yes
+LED_MATRIX_ENABLE = pinmatrix
 ENCODER_ENABLE = yes
 AUDIO_ENABLE = yes

+ 6 - 0
keyboards/clueboard/california/config.h

@@ -22,3 +22,9 @@
     { NO_PIN, B2 } \
 }
 #define UNUSED_PINS
+
+/* Backlight configuration
+ */
+#define BACKLIGHT_LEVELS 10
+#define LED_MATRIX_PINS { A2, B5, A1, B4, B12, B10, A15, A6, B0, B3 }
+#define LED_DRIVER_LED_COUNT 10

+ 2 - 0
keyboards/clueboard/california/rules.mk

@@ -6,5 +6,7 @@ EXTRAKEY_ENABLE = yes  # Audio control and System control
 CONSOLE_ENABLE = yes   # Console for debug
 COMMAND_ENABLE = no    # Commands for debug and configuration
 NKRO_ENABLE = yes      # USB Nkey Rollover
+BACKLIGHT_ENABLE = yes
+LED_MATRIX_ENABLE = pins
 RGBLIGHT_ENABLE = no
 AUDIO_ENABLE = yes

+ 0 - 7
lib/python/milc.py

@@ -96,7 +96,6 @@ def format_ansi(text):
 class ANSIFormatter(logging.Formatter):
     """A log formatter that inserts ANSI color.
     """
-
     def format(self, record):
         msg = super(ANSIFormatter, self).format(record)
         return format_ansi(msg)
@@ -105,7 +104,6 @@ class ANSIFormatter(logging.Formatter):
 class ANSIEmojiLoglevelFormatter(ANSIFormatter):
     """A log formatter that makes the loglevel an emoji on UTF capable terminals.
     """
-
     def format(self, record):
         if UNICODE_SUPPORT:
             record.levelname = EMOJI_LOGLEVELS[record.levelname].format(**ansi_colors)
@@ -115,7 +113,6 @@ class ANSIEmojiLoglevelFormatter(ANSIFormatter):
 class ANSIStrippingFormatter(ANSIFormatter):
     """A log formatter that strips ANSI.
     """
-
     def format(self, record):
         msg = super(ANSIStrippingFormatter, self).format(record)
         return ansi_escape.sub('', msg)
@@ -127,7 +124,6 @@ class Configuration(object):
     This class never raises IndexError, instead it will return None if a
     section or option does not yet exist.
     """
-
     def __contains__(self, key):
         return self._config.__contains__(key)
 
@@ -216,7 +212,6 @@ def handle_store_boolean(self, *args, **kwargs):
 class SubparserWrapper(object):
     """Wrap subparsers so we can populate the normal and the shadow parser.
     """
-
     def __init__(self, cli, submodule, subparser):
         self.cli = cli
         self.submodule = submodule
@@ -249,7 +244,6 @@ class SubparserWrapper(object):
 class MILC(object):
     """MILC - An Opinionated Batteries Included Framework
     """
-
     def __init__(self):
         """Initialize the MILC object.
         """
@@ -620,7 +614,6 @@ class MILC(object):
     def subcommand(self, description, **kwargs):
         """Decorator to register a subcommand.
         """
-
         def subcommand_function(handler):
             return self.add_subcommand(handler, description, **kwargs)
 

+ 1 - 0
lib/python/qmk/cli/list/keyboards.py

@@ -6,6 +6,7 @@ import glob
 
 from milc import cli
 
+
 @cli.subcommand("List the keyboards currently defined within QMK")
 def list_keyboards(cli):
     """List the keyboards currently defined within QMK

+ 0 - 1
lib/python/qmk/errors.py

@@ -1,6 +1,5 @@
 class NoSuchKeyboardError(Exception):
     """Raised when we can't find a keyboard/keymap directory.
     """
-
     def __init__(self, message):
         self.message = message

+ 0 - 1
lib/python/qmk/tests/attrdict.py

@@ -3,7 +3,6 @@ class AttrDict(dict):
 
     This should only be used to mock objects for unit testing. Please do not use this outside of qmk.tests.
     """
-
     def __init__(self, *args, **kwargs):
         super(AttrDict, self).__init__(*args, **kwargs)
         self.__dict__ = self

+ 64 - 26
quantum/led_matrix_drivers.c

@@ -35,13 +35,24 @@
 #    endif
 
 #    include "i2c_master.h"
+#endif
+
+#ifdef LED_MATRIX_PINMATRIX_ENABLE
+#    include "led_matrix_pinmatrix.h"
+#endif
+
+#ifdef LED_MATRIX_PINS_ENABLE
+#    include "led_matrix_pins.h"
+#endif
 
 static void init(void) {
+#if defined(IS31FL3731) || defined(IS31FL3733)
     i2c_init();
+
 #    ifdef IS31FL3731
 #        ifdef LED_DRIVER_ADDR_1
     IS31FL3731_init(LED_DRIVER_ADDR_1);
-#        endif
+#    endif
 #        ifdef LED_DRIVER_ADDR_2
     IS31FL3731_init(LED_DRIVER_ADDR_2);
 #        endif
@@ -69,11 +80,13 @@ static void init(void) {
     for (int index = 0; index < LED_DRIVER_LED_COUNT; index++) {
 #    ifdef IS31FL3731
         IS31FL3731_set_led_control_register(index, true);
-#    else
+#    endif
+#    ifdef IS31FL3733
         IS31FL3733_set_led_control_register(index, true);
 #    endif
     }
-// This actually updates the LED drivers
+
+    // This actually updates the LED drivers
 #    ifdef IS31FL3731
 #        ifdef LED_DRIVER_ADDR_1
     IS31FL3731_update_led_control_registers(LED_DRIVER_ADDR_1, 0);
@@ -101,48 +114,73 @@ static void init(void) {
     IS31FL3733_update_led_control_registers(LED_DRIVER_ADDR_4, 3);
 #        endif
 #    endif
+#endif
+
+#ifdef LED_MATRIX_PINMATRIX_ENABLE
+    led_matrix_pinmatrix_init_pins();
+#endif
+
+#ifdef LED_MATRIX_PINS_ENABLE
+    led_matrix_pins_init_pins();
+#endif
 }
 
 static void flush(void) {
-#    ifdef IS31FL3731
-#        ifdef LED_DRIVER_ADDR_1
+#ifdef IS31FL3731
+#    ifdef LED_DRIVER_ADDR_1
     IS31FL3731_update_pwm_buffers(LED_DRIVER_ADDR_1, 0);
-#        endif
-#        ifdef LED_DRIVER_ADDR_2
+#    endif
+#    ifdef LED_DRIVER_ADDR_2
     IS31FL3731_update_pwm_buffers(LED_DRIVER_ADDR_2, 1);
-#        endif
-#        ifdef LED_DRIVER_ADDR_3
+#    endif
+#    ifdef LED_DRIVER_ADDR_3
     IS31FL3731_update_pwm_buffers(LED_DRIVER_ADDR_3, 2);
-#        endif
-#        ifdef LED_DRIVER_ADDR_4
+#    endif
+#    ifdef LED_DRIVER_ADDR_4
     IS31FL3731_update_pwm_buffers(LED_DRIVER_ADDR_4, 3);
-#        endif
-#    else
-#        ifdef LED_DRIVER_ADDR_1
+#    endif
+#endif
+#ifdef IS31FL3733
+#    ifdef LED_DRIVER_ADDR_1
     IS31FL3733_update_pwm_buffers(LED_DRIVER_ADDR_1, 0);
-#        endif
-#        ifdef LED_DRIVER_ADDR_2
+#    endif
+#    ifdef LED_DRIVER_ADDR_2
     IS31FL3733_update_pwm_buffers(LED_DRIVER_ADDR_2, 1);
-#        endif
-#        ifdef LED_DRIVER_ADDR_3
+#    endif
+#    ifdef LED_DRIVER_ADDR_3
     IS31FL3733_update_pwm_buffers(LED_DRIVER_ADDR_3, 2);
-#        endif
-#        ifdef LED_DRIVER_ADDR_4
+#    endif
+#    ifdef LED_DRIVER_ADDR_4
     IS31FL3733_update_pwm_buffers(LED_DRIVER_ADDR_4, 3);
-#        endif
 #    endif
+#endif
+
+#ifdef LED_MATRIX_PINMATRIX_ENABLE
+    led_matrix_pinmatrix_flush();
+#endif
+
+#ifdef LED_MATRIX_PINS_ENABLE
+    led_matrix_pins_flush();
+#endif
 }
 
 const led_matrix_driver_t led_matrix_driver = {
     .init  = init,
     .flush = flush,
-#    ifdef IS31FL3731
+#ifdef IS31FL3731
     .set_value     = IS31FL3731_set_value,
     .set_value_all = IS31FL3731_set_value_all,
-#    else
+#endif
+#ifdef IS31FL3133
     .set_value = IS31FL3733_set_value,
     .set_value_all = IS31FL3733_set_value_all,
-#    endif
-};
-
 #endif
+#ifdef LED_MATRIX_PINMATRIX_ENABLE
+    .set_value = led_matrix_pinmatrix_set_value,
+    .set_value_all = led_matrix_pinmatrix_set_value_all,
+#endif
+#ifdef LED_MATRIX_PINS_ENABLE
+    .set_value = led_matrix_pins_set_value,
+    .set_value_all = led_matrix_pins_set_value_all,
+#endif
+};

+ 4 - 1
quantum/stm32/proton_c.mk

@@ -3,7 +3,10 @@
 # These are defaults based on what has been implemented for ARM boards
 AUDIO_ENABLE = yes
 RGBLIGHT_ENABLE = no
-BACKLIGHT_ENABLE = no
+
+ifneq ($(strip $(LED_MATRIX_ENABLE)), direct)
+    BACKLIGHT_ENABLE = no
+endif
 
 # The rest of these settings shouldn't change