From f290f40db15d1a96fe7f780dc555c6d72cf1c0b5 Mon Sep 17 00:00:00 2001 From: Alde Rojas Date: Sat, 7 Nov 2020 20:13:01 -0600 Subject: [PATCH 1/9] Rewrite APA102 support The APA102 source was broken by commit 16a15c1cfcbfd0feb2c2cf1383676747e2f97d73 as it did not include the quantum header. This commit addresses that, as well as other issues with transferring bytes over the SPI interface, i.e. it was not setting the clock pin back to low after sending a bit. The deviation when sending the end frame is kept, but updated to the latest from the referenced project. Finally, these changes expose the global LED brightness parameter of the APA102. Brightness values are configurable through `APA102_DEFAULT_BRIGHTNESS` and `APA102_MAX_BRIGHTNESS`. --- drivers/avr/apa102.c | 120 +++++++++++++++++++++++++++---------------- drivers/avr/apa102.h | 23 +++++---- 2 files changed, 87 insertions(+), 56 deletions(-) diff --git a/drivers/avr/apa102.c b/drivers/avr/apa102.c index 740acb5739b7..5e281abbfe81 100644 --- a/drivers/avr/apa102.c +++ b/drivers/avr/apa102.c @@ -21,76 +21,106 @@ */ #include "apa102.h" -#include -#include -#include -#include "debug.h" +#include "quantum.h" -// Setleds for standard RGB -void inline apa102_setleds(LED_TYPE *ledarray, uint16_t leds) { apa102_setleds_pin(ledarray, leds, _BV(RGB_DI_PIN & 0xF), _BV(RGB_CLK_PIN & 0xF)); } +uint8_t apa102_led_brightness = APA102_DEFAULT_BRIGHTNESS; -void static inline apa102_setleds_pin(LED_TYPE *ledarray, uint16_t leds, uint8_t pinmask_DI, uint8_t pinmask_CLK) { +void static apa102_start_frame(void); +void static apa102_end_frame(uint16_t num_leds); + +void static apa102_send_frame(uint8_t red, uint8_t green, uint8_t blue, uint8_t brightness); +void static apa102_send_byte(uint8_t byte); + +void apa102_setleds(LED_TYPE *start_led, uint16_t num_leds) { + LED_TYPE *end = start_led + num_leds; + + apa102_start_frame(); + for (LED_TYPE *led = start_led; led < end; led++) { + apa102_send_frame(led->r, led->g, led->b, apa102_led_brightness); + } + apa102_end_frame(num_leds); +} + +void static apa102_init(void) { setPinOutput(RGB_DI_PIN); setPinOutput(RGB_CLK_PIN); - apa102_send_array((uint8_t *)ledarray, leds) + writePinLow(RGB_DI_PIN); + writePinLow(RGB_CLK_PIN); } -void apa102_send_array(uint8_t *data, uint16_t leds) { // Data is struct of 3 bytes. RGB - leds is number of leds in data - apa102_start_frame(); - while (leds--) { - apa102_send_frame(0xFF000000 | (data->b << 16) | (data->g << 8) | data->r); - data++; +void apa102_set_brightness(uint8_t brightness) { + if (brightness > APA102_MAX_BRIGHTNESS) { + apa102_led_brightness = APA102_MAX_BRIGHTNESS; + } else if (brightness < 0) { + apa102_led_brightness = 0; + } else { + apa102_led_brightness = brightness; } - apa102_end_frame(leds); } -void apa102_send_frame(uint32_t frame) { - for (uint32_t i = 0xFF; i > 0;) { - apa102_send_byte(frame & i); - i = i << 8; - } +void static apa102_send_frame(uint8_t red, uint8_t green, uint8_t blue, uint8_t brightness) { + apa102_send_byte(0b11100000 | brightness); + apa102_send_byte(blue); + apa102_send_byte(green); + apa102_send_byte(red); } -void apa102_start_frame() { apa102_send_frame(0); } +void static apa102_start_frame(void) { + apa102_init(); + apa102_send_byte(0); + apa102_send_byte(0); + apa102_send_byte(0); + apa102_send_byte(0); +} -void apa102_end_frame(uint16_t leds) { +void static apa102_end_frame(uint16_t num_leds) { // This function has been taken from: https://github.com/pololu/apa102-arduino/blob/master/APA102.h // and adapted. The code is MIT licensed. I think thats compatible? - - // We need to send some more bytes to ensure that all the LEDs in the - // chain see their new color and start displaying it. // // The data stream seen by the last LED in the chain will be delayed by // (count - 1) clock edges, because each LED before it inverts the clock // line and delays the data by one clock edge. Therefore, to make sure // the last LED actually receives the data we wrote, the number of extra // edges we send at the end of the frame must be at least (count - 1). - // For the APA102C, that is sufficient. // - // The SK9822 only updates after it sees 32 zero bits followed by one more - // rising edge. To avoid having the update time depend on the color of - // the last LED, we send a dummy 0xFF byte. (Unfortunately, this means - // that partial updates of the beginning of an LED strip are not possible; - // the LED after the last one you are trying to update will be black.) - // After that, to ensure that the last LED in the chain sees 32 zero bits - // and a rising edge, we need to send at least 65 + (count - 1) edges. It - // is sufficent and simpler to just send (5 + count/16) bytes of zeros. + // Assuming we only want to send these edges in groups of size K, the + // C/C++ expression for the minimum number of groups to send is: // - // We are ignoring the specification for the end frame in the APA102/SK9822 - // datasheets because it does not actually ensure that all the LEDs will - // start displaying their new colors right away. - - apa102_send_byte(0xFF); - for (uint16_t i = 0; i < 5 + leds / 16; i++) { + // ((count - 1) + (K - 1)) / K + // + // The C/C++ expression above is just (count - 1) divided by K, + // rounded up to the nearest whole number if there is a remainder. + // + // We set K to 16 and use the formula above as the number of frame-end + // bytes to transfer. Each byte has 16 clock edges. + // + // We are ignoring the specification for the end frame in the APA102 + // datasheet, which says to send 0xFF four times, because it does not work + // when you have 66 LEDs or more, and also it results in unwanted white + // pixels if you try to update fewer LEDs than are on your LED strip. + uint16_t iterations = (num_leds + 14) / 16; + for (uint16_t i = 0; i < iterations; i++) { apa102_send_byte(0); } + + apa102_init(); } -void apa102_send_byte(uint8_t byte) { - uint8_t i; - for (i = 0; i < 8; i++) { - writePin(RGB_DI_PIN, !!(byte & (1 << (7 - i)))); - writePinHigh(RGB_CLK_PIN); - } +#define APA102_SEND_BIT(byte, bit) \ + do { \ + writePin(RGB_DI_PIN, (byte >> bit) & 1); \ + writePinHigh(RGB_CLK_PIN); \ + writePinLow(RGB_CLK_PIN); \ + } while (0) + +void static apa102_send_byte(uint8_t byte) { + APA102_SEND_BIT(byte, 7); + APA102_SEND_BIT(byte, 6); + APA102_SEND_BIT(byte, 5); + APA102_SEND_BIT(byte, 4); + APA102_SEND_BIT(byte, 3); + APA102_SEND_BIT(byte, 2); + APA102_SEND_BIT(byte, 1); + APA102_SEND_BIT(byte, 0); } diff --git a/drivers/avr/apa102.h b/drivers/avr/apa102.h index d4c1e18ee1b7..2b213611c4ae 100644 --- a/drivers/avr/apa102.h +++ b/drivers/avr/apa102.h @@ -22,24 +22,25 @@ #pragma once -#include -#include - #include "color.h" +#ifndef APA102_DEFAULT_BRIGHTNESS +# define APA102_DEFAULT_BRIGHTNESS 31 +#endif + +#define APA102_MAX_BRIGHTNESS 31 + +extern uint8_t apa102_let_brightness; + /* User Interface * * Input: - * ledarray: An array of GRB data describing the LED colors - * number_of_leds: The number of LEDs to write - * pinmask (optional): Bitmask describing the output bin. e.g. _BV(PB0) + * start_led: An array of GRB data describing the LED colors + * num_leds: The number of LEDs to write * * The functions will perform the following actions: * - Set the data-out pin as output * - Send out the LED data - * - Wait 50�s to reset the LEDs */ - -void apa102_setleds(LED_TYPE *ledarray, uint16_t number_of_leds); -void apa102_setleds_pin(LED_TYPE *ledarray, uint16_t number_of_leds, uint8_t pinmask); -void apa102_setleds_rgbw(LED_TYPE *ledarray, uint16_t number_of_leds); +void apa102_setleds(LED_TYPE *start_led, uint16_t num_leds); +void apa102_set_brightness(uint8_t brightness); From bf55f58f7c2dd8daeb617b49b9bb70cbbb187e91 Mon Sep 17 00:00:00 2001 From: Alde Rojas Date: Sun, 8 Nov 2020 19:28:02 -0600 Subject: [PATCH 2/9] Fix typo in led brightness extern --- drivers/avr/apa102.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/avr/apa102.h b/drivers/avr/apa102.h index 2b213611c4ae..90cb0348755c 100644 --- a/drivers/avr/apa102.h +++ b/drivers/avr/apa102.h @@ -30,7 +30,7 @@ #define APA102_MAX_BRIGHTNESS 31 -extern uint8_t apa102_let_brightness; +extern uint8_t apa102_led_brightness; /* User Interface * From 6e71ac0dae495505411d553afb347268557e0177 Mon Sep 17 00:00:00 2001 From: Aldehir Rojas Date: Sun, 29 Nov 2020 06:51:51 -0600 Subject: [PATCH 3/9] Move driver out of AVR directory and add delay for ARM --- drivers/{avr => }/apa102.c | 56 +++++++++++++++++++++++++++++++++----- drivers/{avr => }/apa102.h | 0 2 files changed, 49 insertions(+), 7 deletions(-) rename drivers/{avr => }/apa102.c (72%) rename drivers/{avr => }/apa102.h (100%) diff --git a/drivers/avr/apa102.c b/drivers/apa102.c similarity index 72% rename from drivers/avr/apa102.c rename to drivers/apa102.c index 5e281abbfe81..cabd8532bf83 100644 --- a/drivers/avr/apa102.c +++ b/drivers/apa102.c @@ -23,6 +23,55 @@ #include "apa102.h" #include "quantum.h" +#if defined(__AVR__) +# define delay_high() \ + do { \ + } while (0) +# define delay_low() \ + do { \ + } while (0) +#elif defined(PROTOCOL_CHIBIOS) +/* This was taken from the WS2812 library, but NUMBER_NOPS and NOP_FUDGE are + * adjusted for shorter delays. */ +# include "hal.h" + +# ifndef NOP_FUDGE +# if defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F3XX) || defined(STM32F4XX) || defined(STM32L0XX) +# define NOP_FUDGE 0.8 +# else +# error("NOP_FUDGE configuration required") +# define NOP_FUDGE 1 // this just pleases the compile so the above error is easier to spot +# endif +# endif + +# define NUMBER_NOPS 3 +# define CYCLES_PER_SEC (STM32_SYSCLK / NUMBER_NOPS * NOP_FUDGE) +# define NS_PER_SEC (1000000000L) // Note that this has to be SIGNED since we want to be able to check for negative values of derivatives +# define NS_PER_CYCLE (NS_PER_SEC / CYCLES_PER_SEC) +# define NS_TO_CYCLES(n) ((n) / NS_PER_CYCLE) + +# define wait_ns(x) \ + do { \ + for (int i = 0; i < NS_TO_CYCLES(x); i++) { \ + __asm__ volatile("nop\n\t" \ + "nop\n\t" \ + "nop\n\t"); \ + } \ + } while (0) + +# define delay_high() wait_ns(200) +# define delay_low() wait_ns(80) +#endif + +#define APA102_SEND_BIT(byte, bit) \ + do { \ + writePin(RGB_DI_PIN, (byte >> bit) & 1); \ + writePinHigh(RGB_CLK_PIN); \ + delay_high(); \ + writePinLow(RGB_CLK_PIN); \ + delay_low(); \ + } while (0) + uint8_t apa102_led_brightness = APA102_DEFAULT_BRIGHTNESS; void static apa102_start_frame(void); @@ -107,13 +156,6 @@ void static apa102_end_frame(uint16_t num_leds) { apa102_init(); } -#define APA102_SEND_BIT(byte, bit) \ - do { \ - writePin(RGB_DI_PIN, (byte >> bit) & 1); \ - writePinHigh(RGB_CLK_PIN); \ - writePinLow(RGB_CLK_PIN); \ - } while (0) - void static apa102_send_byte(uint8_t byte) { APA102_SEND_BIT(byte, 7); APA102_SEND_BIT(byte, 6); diff --git a/drivers/avr/apa102.h b/drivers/apa102.h similarity index 100% rename from drivers/avr/apa102.h rename to drivers/apa102.h From bf249d6600770bbb2fb66b26f3495ac40f687c9f Mon Sep 17 00:00:00 2001 From: Mikkel Jeppesen <2756925+Duckle29@users.noreply.github.com> Date: Wed, 18 Nov 2020 23:58:34 +0100 Subject: [PATCH 4/9] Experimental APA102 support on AVR and ARM Co-authored-by: Alde Rojas --- common_features.mk | 47 ++++++++++++++++++++++++++++++-------- docs/feature_rgb_matrix.md | 22 ++++++++++++++++++ docs/feature_rgblight.md | 11 ++++++++- drivers/apa102.c | 11 +++++---- 4 files changed, 77 insertions(+), 14 deletions(-) diff --git a/common_features.mk b/common_features.mk index 8ac53ec45a5f..39756faea257 100644 --- a/common_features.mk +++ b/common_features.mk @@ -154,18 +154,38 @@ else endif endif -ifeq ($(strip $(RGBLIGHT_ENABLE)), yes) - POST_CONFIG_H += $(QUANTUM_DIR)/rgblight_post_config.h - OPT_DEFS += -DRGBLIGHT_ENABLE - SRC += $(QUANTUM_DIR)/color.c - SRC += $(QUANTUM_DIR)/rgblight.c - CIE1931_CURVE := yes - RGB_KEYCODES_ENABLE := yes - ifeq ($(strip $(RGBLIGHT_CUSTOM_DRIVER)), yes) - OPT_DEFS += -DRGBLIGHT_CUSTOM_DRIVER +RGBLIGHT_ENABLE ?= no +VALID_RGBLIGHT_TYPES := WS2812 APA102 custom + +ifeq ($(strip $(RGBLIGHT_CUSTOM_DRIVER)), yes) + RGBLIGHT_DRIVER ?= custom +else + RGBLIGHT_DRIVER ?= WS2812 +endif + +ifneq ($(strip $(RGBLIGHT_ENABLE)), no) + ifeq ($(filter $(RGBLIGHT_DRIVER),$(VALID_RGBLIGHT_TYPES)),) + $(error RGBLIGHT_DRIVER="$(RGBLIGHT_DRIVER)" is not a valid RGB type) else + POST_CONFIG_H += $(QUANTUM_DIR)/rgblight_post_config.h + OPT_DEFS += -DRGBLIGHT_ENABLE + SRC += $(QUANTUM_DIR)/color.c + SRC += $(QUANTUM_DIR)/rgblight.c + CIE1931_CURVE := yes + RGB_KEYCODES_ENABLE := yes + endif + + ifeq ($(strip $(RGBLIGHT_DRIVER)), WS2812) WS2812_DRIVER_REQUIRED := yes endif + + ifeq ($(strip $(RGBLIGHT_DRIVER)), APA102) + APA102_DRIVER_REQUIRED := yes + endif + + ifeq ($(strip $(RGBLIGHT_DRIVER)), custom) + OPT_DEFS += -DRGBLIGHT_CUSTOM_DRIVER + endif endif @@ -243,6 +263,11 @@ endif WS2812_DRIVER_REQUIRED := yes endif + ifeq ($(strip $(RGB_MATRIX_DRIVER)), APA102) + OPT_DEFS += -DAPA102 + APA102_DRIVER_REQUIRED := yes + endif + ifeq ($(strip $(RGB_MATRIX_CUSTOM_KB)), yes) OPT_DEFS += -DRGB_MATRIX_CUSTOM_KB endif @@ -345,6 +370,10 @@ ifeq ($(strip $(WS2812_DRIVER_REQUIRED)), yes) endif endif +ifeq ($(strip $(APA102_DRIVER_REQUIRED)), yes) + SRC += apa102.c +endif + ifeq ($(strip $(VISUALIZER_ENABLE)), yes) CIE1931_CURVE := yes endif diff --git a/docs/feature_rgb_matrix.md b/docs/feature_rgb_matrix.md index f8b0653551f4..02db0e117b55 100644 --- a/docs/feature_rgb_matrix.md +++ b/docs/feature_rgb_matrix.md @@ -129,6 +129,28 @@ Configure the hardware via your `config.h`: --- +### APA102 :id=apa102 + +There is basic support for APA102 based addressable LED strands. To enable it, add this to your `rules.mk`: + +```makefile +RGB_MATRIX_ENABLE = yes +RGB_MATRIX_DRIVER = APA102 +``` + +Configure the hardware via your `config.h`: + +```c +// The pin connected to the data pin of the LEDs +#define RGB_DI_PIN D7 +// The pin connected to the clock pin of the LEDs +#define RGB_CI_PIN D6 +// The number of LEDs connected +#define DRIVER_LED_TOTAL 70 +``` + +--- + From this point forward the configuration is the same for all the drivers. The `led_config_t` struct provides a key electrical matrix to led index lookup table, what the physical position of each LED is on the board, and what type of key or usage the LED if the LED represents. Here is a brief example: ```c diff --git a/docs/feature_rgblight.md b/docs/feature_rgblight.md index 762056b34320..f1178c679dbe 100644 --- a/docs/feature_rgblight.md +++ b/docs/feature_rgblight.md @@ -10,6 +10,7 @@ Currently QMK supports the following addressable LEDs (however, the white LED in * WS2811, WS2812, WS2812B, WS2812C, etc. * SK6812, SK6812MINI, SK6805 + * APA102 These LEDs are called "addressable" because instead of using a wire per color, each LED contains a small microchip that understands a special protocol sent over a single wire. The chip passes on the remaining data to the next LED, allowing them to be chained together. In this way, you can easily control the color of the individual LEDs. @@ -21,11 +22,19 @@ On keyboards with onboard RGB LEDs, it is usually enabled by default. If it is n RGBLIGHT_ENABLE = yes ``` -At minimum you must define the data pin your LED strip is connected to, and the number of LEDs in the strip, in your `config.h`. If your keyboard has onboard RGB LEDs, and you are simply creating a keymap, you usually won't need to modify these. +For APA102 LEDs, add the following to your `rules.mk`: + +```make +RGBLIGHT_ENABLE = yes +RGBLIGHT_DRIVER = APA102 +``` + +At minimum you must define the data pin your LED strip is connected to, and the number of LEDs in the strip, in your `config.h`. For APA102 LEDs, you must also define the clock pin. If your keyboard has onboard RGB LEDs, and you are simply creating a keymap, you usually won't need to modify these. |Define |Description | |---------------|---------------------------------------------------------------------------------------------------------| |`RGB_DI_PIN` |The pin connected to the data pin of the LEDs | +|`RGB_CI_PIN` |The pin connected to the clock pin of the LEDs (APA102 only) | |`RGBLED_NUM` |The number of LEDs connected | |`RGBLED_SPLIT` |(Optional) For split keyboards, the number of LEDs connected on each half directly wired to `RGB_DI_PIN` | diff --git a/drivers/apa102.c b/drivers/apa102.c index cabd8532bf83..623c89c4288a 100644 --- a/drivers/apa102.c +++ b/drivers/apa102.c @@ -66,9 +66,9 @@ #define APA102_SEND_BIT(byte, bit) \ do { \ writePin(RGB_DI_PIN, (byte >> bit) & 1); \ - writePinHigh(RGB_CLK_PIN); \ + writePinHigh(RGB_CI_PIN); \ delay_high(); \ - writePinLow(RGB_CLK_PIN); \ + writePinLow(RGB_CI_PIN); \ delay_low(); \ } while (0) @@ -90,12 +90,15 @@ void apa102_setleds(LED_TYPE *start_led, uint16_t num_leds) { apa102_end_frame(num_leds); } +// Overwrite the default rgblight_call_driver to use apa102 driver +void rgblight_call_driver(LED_TYPE *start_led, uint8_t num_leds) { apa102_setleds(start_led, num_leds); } + void static apa102_init(void) { setPinOutput(RGB_DI_PIN); - setPinOutput(RGB_CLK_PIN); + setPinOutput(RGB_CI_PIN); writePinLow(RGB_DI_PIN); - writePinLow(RGB_CLK_PIN); + writePinLow(RGB_CI_PIN); } void apa102_set_brightness(uint8_t brightness) { From 5a0610169d06caf782a48151aafae0f6d3ad417f Mon Sep 17 00:00:00 2001 From: Alde Rojas Date: Mon, 30 Nov 2020 23:20:40 -0600 Subject: [PATCH 5/9] Refactor apa102_send_byte() calls to a loop --- drivers/apa102.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/apa102.c b/drivers/apa102.c index 623c89c4288a..da5246755e59 100644 --- a/drivers/apa102.c +++ b/drivers/apa102.c @@ -120,10 +120,9 @@ void static apa102_send_frame(uint8_t red, uint8_t green, uint8_t blue, uint8_t void static apa102_start_frame(void) { apa102_init(); - apa102_send_byte(0); - apa102_send_byte(0); - apa102_send_byte(0); - apa102_send_byte(0); + for (uint16_t i = 0; i < 4; i++) { + apa102_send_byte(0); + } } void static apa102_end_frame(uint16_t num_leds) { From 59268876bd08d7a53d149c80497dbb6da3364339 Mon Sep 17 00:00:00 2001 From: Mikkel <2756925+Duckle29@users.noreply.github.com> Date: Sun, 29 Nov 2020 22:52:51 +0100 Subject: [PATCH 6/9] Implement io_wait function for ARM --- drivers/apa102.c | 58 ++++++++++++++++++------------------------------ 1 file changed, 22 insertions(+), 36 deletions(-) diff --git a/drivers/apa102.c b/drivers/apa102.c index da5246755e59..f3cdb9752686 100644 --- a/drivers/apa102.c +++ b/drivers/apa102.c @@ -23,53 +23,39 @@ #include "apa102.h" #include "quantum.h" -#if defined(__AVR__) -# define delay_high() \ - do { \ - } while (0) -# define delay_low() \ - do { \ - } while (0) -#elif defined(PROTOCOL_CHIBIOS) -/* This was taken from the WS2812 library, but NUMBER_NOPS and NOP_FUDGE are - * adjusted for shorter delays. */ -# include "hal.h" - -# ifndef NOP_FUDGE +#ifndef APA102_NOPS +# if defined(__AVR__) +# define APA102_NOPS 0 // AVR at 16 MHz already spends 62.5 ns per clock, so no extra delay is needed +# elif defined(PROTOCOL_CHIBIOS) + +# include "hal.h" # if defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F3XX) || defined(STM32F4XX) || defined(STM32L0XX) -# define NOP_FUDGE 0.8 +# define APA102_NOPS (100 / (1000000000L / (STM32_SYSCLK / 4))) // This calculates how many loops of 4 nops to run to delay 100 ns # else -# error("NOP_FUDGE configuration required") -# define NOP_FUDGE 1 // this just pleases the compile so the above error is easier to spot +# error("APA102_NOPS configuration required") +# define APA102_NOPS 0 // this just pleases the compile so the above error is easier to spot # endif # endif - -# define NUMBER_NOPS 3 -# define CYCLES_PER_SEC (STM32_SYSCLK / NUMBER_NOPS * NOP_FUDGE) -# define NS_PER_SEC (1000000000L) // Note that this has to be SIGNED since we want to be able to check for negative values of derivatives -# define NS_PER_CYCLE (NS_PER_SEC / CYCLES_PER_SEC) -# define NS_TO_CYCLES(n) ((n) / NS_PER_CYCLE) - -# define wait_ns(x) \ - do { \ - for (int i = 0; i < NS_TO_CYCLES(x); i++) { \ - __asm__ volatile("nop\n\t" \ - "nop\n\t" \ - "nop\n\t"); \ - } \ - } while (0) - -# define delay_high() wait_ns(200) -# define delay_low() wait_ns(80) #endif +#define io_wait \ + do { \ + for (int i = 0; i < APA102_NOPS; i++) { \ + __asm__ volatile("nop\n\t" \ + "nop\n\t" \ + "nop\n\t" \ + "nop\n\t"); \ + } \ + } while (0) + #define APA102_SEND_BIT(byte, bit) \ do { \ writePin(RGB_DI_PIN, (byte >> bit) & 1); \ + io_wait; \ writePinHigh(RGB_CI_PIN); \ - delay_high(); \ + io_wait; \ writePinLow(RGB_CI_PIN); \ - delay_low(); \ + io_wait; \ } while (0) uint8_t apa102_led_brightness = APA102_DEFAULT_BRIGHTNESS; From c30983394410401bb8f7f4e676a91aca536f9393 Mon Sep 17 00:00:00 2001 From: Alde Rojas Date: Wed, 2 Dec 2020 18:49:06 -0600 Subject: [PATCH 7/9] Move APA102 drivers to own directory, fix copyright notice --- common_features.mk | 1 + drivers/{ => apa102}/apa102.c | 9 ++------- drivers/{ => apa102}/apa102.h | 9 ++------- 3 files changed, 5 insertions(+), 14 deletions(-) rename drivers/{ => apa102}/apa102.c (97%) rename drivers/{ => apa102}/apa102.h (86%) diff --git a/common_features.mk b/common_features.mk index 39756faea257..c4919caa5101 100644 --- a/common_features.mk +++ b/common_features.mk @@ -371,6 +371,7 @@ ifeq ($(strip $(WS2812_DRIVER_REQUIRED)), yes) endif ifeq ($(strip $(APA102_DRIVER_REQUIRED)), yes) + COMMON_VPATH += $(DRIVER_PATH)/apa102 SRC += apa102.c endif diff --git a/drivers/apa102.c b/drivers/apa102/apa102.c similarity index 97% rename from drivers/apa102.c rename to drivers/apa102/apa102.c index f3cdb9752686..7396dc3c551d 100644 --- a/drivers/apa102.c +++ b/drivers/apa102/apa102.c @@ -1,10 +1,5 @@ -/* - * APA102 lib V1.0a - * - * Controls APA102 RGB-LEDs - * Author: Mikkel (Duckle29 on GitHub) - * - * Dec 22th, 2017 v1.0a Initial Version +/* Copyright 2020 Aldehir Rojas + * Copyright 2017 Mikkel (Duckle29) * * 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 diff --git a/drivers/apa102.h b/drivers/apa102/apa102.h similarity index 86% rename from drivers/apa102.h rename to drivers/apa102/apa102.h index 90cb0348755c..58cf020c1e16 100644 --- a/drivers/apa102.h +++ b/drivers/apa102/apa102.h @@ -1,10 +1,5 @@ -/* - * light weight WS2812 lib include - * - * Version 2.3 - Nev 29th 2015 - * Author: Tim (cpldcpu@gmail.com) - * - * Please do not change this file! All configuration is handled in "ws2812_config.h" +/* Copyright 2020 Aldehir Rojas + * Copyright 2017 Mikkel (Duckle29) * * 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 From b04c328703706f83a63a9b1031fe49520651e68b Mon Sep 17 00:00:00 2001 From: Alde Rojas Date: Wed, 2 Dec 2020 19:04:53 -0600 Subject: [PATCH 8/9] Add APA102 keymap to handwired/onekey --- keyboards/handwired/onekey/elite_c/config.h | 1 + keyboards/handwired/onekey/keymaps/apa102/config.h | 5 +++++ keyboards/handwired/onekey/keymaps/apa102/keymap.c | 14 ++++++++++++++ keyboards/handwired/onekey/keymaps/apa102/rules.mk | 2 ++ keyboards/handwired/onekey/promicro/config.h | 1 + keyboards/handwired/onekey/proton_c/config.h | 1 + 6 files changed, 24 insertions(+) create mode 100644 keyboards/handwired/onekey/keymaps/apa102/config.h create mode 100644 keyboards/handwired/onekey/keymaps/apa102/keymap.c create mode 100644 keyboards/handwired/onekey/keymaps/apa102/rules.mk diff --git a/keyboards/handwired/onekey/elite_c/config.h b/keyboards/handwired/onekey/elite_c/config.h index 167373cd39b6..02c81ce7439b 100644 --- a/keyboards/handwired/onekey/elite_c/config.h +++ b/keyboards/handwired/onekey/elite_c/config.h @@ -25,5 +25,6 @@ #define BACKLIGHT_PIN B6 #define RGB_DI_PIN F6 +#define RGB_CI_PIN B1 #define ADC_PIN F6 diff --git a/keyboards/handwired/onekey/keymaps/apa102/config.h b/keyboards/handwired/onekey/keymaps/apa102/config.h new file mode 100644 index 000000000000..aeb22a261ba9 --- /dev/null +++ b/keyboards/handwired/onekey/keymaps/apa102/config.h @@ -0,0 +1,5 @@ +#pragma once + +#define RGBLED_NUM 40 +#define APA102_DEFAULT_BRIGHTNESS 5 +#define RGBLIGHT_ANIMATIONS diff --git a/keyboards/handwired/onekey/keymaps/apa102/keymap.c b/keyboards/handwired/onekey/keymaps/apa102/keymap.c new file mode 100644 index 000000000000..700755a452b5 --- /dev/null +++ b/keyboards/handwired/onekey/keymaps/apa102/keymap.c @@ -0,0 +1,14 @@ +#include QMK_KEYBOARD_H +#include "apa102.h" // Only needed if you want to use the global brightness function + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + LAYOUT_ortho_1x1(RGB_MOD) +}; + +void keyboard_post_init_user(void) { + apa102_set_brightness(5); + + rgblight_enable_noeeprom(); + rgblight_sethsv_noeeprom_cyan(); + rgblight_mode_noeeprom(RGBLIGHT_MODE_RAINBOW_SWIRL); +} diff --git a/keyboards/handwired/onekey/keymaps/apa102/rules.mk b/keyboards/handwired/onekey/keymaps/apa102/rules.mk new file mode 100644 index 000000000000..70932cb75168 --- /dev/null +++ b/keyboards/handwired/onekey/keymaps/apa102/rules.mk @@ -0,0 +1,2 @@ +RGBLIGHT_ENABLE = yes +RGBLIGHT_DRIVER = APA102 diff --git a/keyboards/handwired/onekey/promicro/config.h b/keyboards/handwired/onekey/promicro/config.h index 167373cd39b6..02c81ce7439b 100644 --- a/keyboards/handwired/onekey/promicro/config.h +++ b/keyboards/handwired/onekey/promicro/config.h @@ -25,5 +25,6 @@ #define BACKLIGHT_PIN B6 #define RGB_DI_PIN F6 +#define RGB_CI_PIN B1 #define ADC_PIN F6 diff --git a/keyboards/handwired/onekey/proton_c/config.h b/keyboards/handwired/onekey/proton_c/config.h index 3ba4ba649962..a364bbee341f 100644 --- a/keyboards/handwired/onekey/proton_c/config.h +++ b/keyboards/handwired/onekey/proton_c/config.h @@ -28,5 +28,6 @@ #define BACKLIGHT_PAL_MODE 2 #define RGB_DI_PIN A0 +#define RGB_CI_PIN B13 #define ADC_PIN A0 From d8ae1cceadc00ff37613da4e4fcaa23117c84f11 Mon Sep 17 00:00:00 2001 From: Alde Rojas Date: Wed, 2 Dec 2020 19:08:15 -0600 Subject: [PATCH 9/9] Simplify RGBLIGHT_ENABLE/DRIVER option handling --- common_features.mk | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common_features.mk b/common_features.mk index c4919caa5101..95b59937cdd0 100644 --- a/common_features.mk +++ b/common_features.mk @@ -159,11 +159,11 @@ VALID_RGBLIGHT_TYPES := WS2812 APA102 custom ifeq ($(strip $(RGBLIGHT_CUSTOM_DRIVER)), yes) RGBLIGHT_DRIVER ?= custom -else - RGBLIGHT_DRIVER ?= WS2812 endif -ifneq ($(strip $(RGBLIGHT_ENABLE)), no) +ifeq ($(strip $(RGBLIGHT_ENABLE)), yes) + RGBLIGHT_DRIVER ?= WS2812 + ifeq ($(filter $(RGBLIGHT_DRIVER),$(VALID_RGBLIGHT_TYPES)),) $(error RGBLIGHT_DRIVER="$(RGBLIGHT_DRIVER)" is not a valid RGB type) else