aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Challis <git@zvecr.com>2019-11-07 13:10:29 +0000
committerGitHub <noreply@github.com>2019-11-07 13:10:29 +0000
commit1ea0cac998cab60c8b2aa64ba4bd995acbece4b4 (patch)
treeb0d66dee00794334767db6bec00dbf8c5576b28f
parentb9610091f520f7f20d20964101ae28f7b5f77de2 (diff)
downloadqmk_firmware-1ea0cac998cab60c8b2aa64ba4bd995acbece4b4.tar.gz
qmk_firmware-1ea0cac998cab60c8b2aa64ba4bd995acbece4b4.zip
ARM - ws2812 bitbang (#7173)
* Initial ARM bitbang ws2812 driver * Unify chibios platform to run rgblight_task * Remove 'avr only' comments from ws2812 docs * Remove 'avr only' comments from ws2812 docs * Unify chibios platform to run rgblight_task - review comments * Remove debug flags from keymap * Add comments from review * Add defines for STM32L0XX * Attempt to get arm ws2812 working on multiple gcc versions
-rw-r--r--docs/feature_rgb_matrix.md2
-rw-r--r--docs/feature_rgblight.md2
-rw-r--r--docs/hardware_drivers.md2
-rw-r--r--docs/ws2812_driver.md13
-rw-r--r--drivers/arm/ws2812.c101
-rw-r--r--drivers/arm/ws2812.h17
-rw-r--r--keyboards/handwired/onekey/bluepill/config.h2
-rw-r--r--keyboards/handwired/onekey/keymaps/rgb/config.h4
-rw-r--r--keyboards/handwired/onekey/keymaps/rgb/keymap.c11
-rw-r--r--keyboards/handwired/onekey/keymaps/rgb/rules.mk1
-rw-r--r--keyboards/handwired/onekey/proton_c/config.h2
-rw-r--r--keyboards/handwired/onekey/stm32f0_disco/config.h2
-rw-r--r--quantum/stm32/proton_c.mk2
-rw-r--r--tmk_core/protocol/chibios/main.c8
14 files changed, 162 insertions, 7 deletions
diff --git a/docs/feature_rgb_matrix.md b/docs/feature_rgb_matrix.md
index b2850c3cf..3e69361fb 100644
--- a/docs/feature_rgb_matrix.md
+++ b/docs/feature_rgb_matrix.md
@@ -107,7 +107,7 @@ Where `X_Y` is the location of the LED in the matrix defined by [the datasheet](
107 107
108--- 108---
109 109
110### WS2812 (AVR only) 110### WS2812
111 111
112There is basic support for addressable RGB matrix lighting with a WS2811/WS2812{a,b,c} addressable LED strand. To enable it, add this to your `rules.mk`: 112There is basic support for addressable RGB matrix lighting with a WS2811/WS2812{a,b,c} addressable LED strand. To enable it, add this to your `rules.mk`:
113 113
diff --git a/docs/feature_rgblight.md b/docs/feature_rgblight.md
index be4ddfa72..397dde587 100644
--- a/docs/feature_rgblight.md
+++ b/docs/feature_rgblight.md
@@ -6,7 +6,7 @@ QMK has the ability to control RGB LEDs attached to your keyboard. This is commo
6 6
7Some keyboards come with RGB LEDs preinstalled. Others must have them installed after the fact. See the [Hardware Modification](#hardware-modification) section for information on adding RGB lighting to your keyboard. 7Some keyboards come with RGB LEDs preinstalled. Others must have them installed after the fact. See the [Hardware Modification](#hardware-modification) section for information on adding RGB lighting to your keyboard.
8 8
9Currently QMK supports the following addressable LEDs on AVR microcontrollers (however, the white LED in RGBW variants is not supported): 9Currently QMK supports the following addressable LEDs (however, the white LED in RGBW variants is not supported):
10 10
11 * WS2811, WS2812, WS2812B, WS2812C, etc. 11 * WS2811, WS2812, WS2812B, WS2812C, etc.
12 * SK6812, SK6812MINI, SK6805 12 * SK6812, SK6812MINI, SK6805
diff --git a/docs/hardware_drivers.md b/docs/hardware_drivers.md
index 321ba2a4b..165187795 100644
--- a/docs/hardware_drivers.md
+++ b/docs/hardware_drivers.md
@@ -22,7 +22,7 @@ Support for SSD1306 based OLED displays. For more information see the [OLED Driv
22 22
23You can make use of uGFX within QMK to drive character and graphic LCDs, LED arrays, OLED, TFT, and other display technologies. This needs to be better documented, if you are trying to do this and reading the code doesn't help please [open an issue](https://github.com/qmk/qmk_firmware/issues/new) and we can help you through the process. 23You can make use of uGFX within QMK to drive character and graphic LCDs, LED arrays, OLED, TFT, and other display technologies. This needs to be better documented, if you are trying to do this and reading the code doesn't help please [open an issue](https://github.com/qmk/qmk_firmware/issues/new) and we can help you through the process.
24 24
25## WS2812 (AVR Only) 25## WS2812
26 26
27Support for WS2811/WS2812{a,b,c} LED's. For more information see the [RGB Light](feature_rgblight.md) page. 27Support for WS2811/WS2812{a,b,c} LED's. For more information see the [RGB Light](feature_rgblight.md) page.
28 28
diff --git a/docs/ws2812_driver.md b/docs/ws2812_driver.md
index 6fa5d324c..67481c458 100644
--- a/docs/ws2812_driver.md
+++ b/docs/ws2812_driver.md
@@ -1,13 +1,22 @@
1# WS2812 Driver 1# WS2812 Driver
2This driver powers the [RGB Lighting](feature_rgblight.md) and [RGB Matrix](feature_rgb_matrix.md) features. 2This driver powers the [RGB Lighting](feature_rgblight.md) and [RGB Matrix](feature_rgb_matrix.md) features.
3 3
4Currently QMK supports the following addressable LEDs on AVR microcontrollers (however, the white LED in RGBW variants is not supported): 4Currently QMK supports the following addressable LEDs (however, the white LED in RGBW variants is not supported):
5 5
6 WS2811, WS2812, WS2812B, WS2812C, etc. 6 WS2811, WS2812, WS2812B, WS2812C, etc.
7 SK6812, SK6812MINI, SK6805 7 SK6812, SK6812MINI, SK6805
8 8
9These 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. 9These 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.
10 10
11## Supported Driver Types
12
13| | AVR | ARM |
14|----------|--------------------|--------------------|
15| bit bang | :heavy_check_mark: | :heavy_check_mark: |
16| I2C | :heavy_check_mark: | |
17| SPI | | Soon™ |
18| PWM | | Soon™ |
19
11## Driver configuration 20## Driver configuration
12 21
13### Bitbang 22### Bitbang
@@ -17,7 +26,7 @@ Default driver, the absence of configuration assumes this driver. To configure i
17WS2812_DRIVER = bitbang 26WS2812_DRIVER = bitbang
18``` 27```
19 28
20!> ARM does not yet support WS2182. Progress is being made, but we are not quite there, yet. 29!> This driver is not hardware accelerated and may not be performant on heavily loaded systems.
21 30
22### I2C 31### I2C
23Targeting boards where WS2812 support is offloaded to a 2nd MCU. Currently the driver is limited to AVR given the known consumers are ps2avrGB/BMC. To configure it, add this to your rules.mk: 32Targeting boards where WS2812 support is offloaded to a 2nd MCU. Currently the driver is limited to AVR given the known consumers are ps2avrGB/BMC. To configure it, add this to your rules.mk:
diff --git a/drivers/arm/ws2812.c b/drivers/arm/ws2812.c
index 2094e5009..b076eff33 100644
--- a/drivers/arm/ws2812.c
+++ b/drivers/arm/ws2812.c
@@ -1 +1,100 @@
1#error("NOT SUPPORTED") \ No newline at end of file 1#include "quantum.h"
2#include "ws2812.h"
3#include "ch.h"
4#include "hal.h"
5
6/* Adapted from https://github.com/bigjosh/SimpleNeoPixelDemo/ */
7
8#ifndef NOP_FUDGE
9# if defined(STM32F1XX) || defined(STM32F1xx) || defined(STM32F0XX) || defined(STM32F0xx) || defined(STM32F3XX) || defined(STM32F3xx) || defined(STM32L0XX) || defined(STM32L0xx)
10# define NOP_FUDGE 0.4
11# else
12# error("NOP_FUDGE configuration required")
13# define NOP_FUDGE 1 // this just pleases the compile so the above error is easier to spot
14# endif
15#endif
16
17#define NUMBER_NOPS 6
18#define CYCLES_PER_SEC (STM32_SYSCLK / NUMBER_NOPS * NOP_FUDGE)
19#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
20#define NS_PER_CYCLE (NS_PER_SEC / CYCLES_PER_SEC)
21#define NS_TO_CYCLES(n) ((n) / NS_PER_CYCLE)
22
23#define wait_ns(x) \
24 do { \
25 for (int i = 0; i < NS_TO_CYCLES(x); i++) { \
26 __asm__ volatile("nop\n\t" \
27 "nop\n\t" \
28 "nop\n\t" \
29 "nop\n\t" \
30 "nop\n\t" \
31 "nop\n\t"); \
32 } \
33 } while (0)
34
35// These are the timing constraints taken mostly from the WS2812 datasheets
36// These are chosen to be conservative and avoid problems rather than for maximum throughput
37
38#define T1H 900 // Width of a 1 bit in ns
39#define T1L (1250 - T1H) // Width of a 1 bit in ns
40
41#define T0H 350 // Width of a 0 bit in ns
42#define T0L (1250 - T0H) // Width of a 0 bit in ns
43
44// The reset gap can be 6000 ns, but depending on the LED strip it may have to be increased
45// to values like 600000 ns. If it is too small, the pixels will show nothing most of the time.
46#define RES 10000 // Width of the low gap between bits to cause a frame to latch
47
48void sendByte(uint8_t byte) {
49 // WS2812 protocol wants most significant bits first
50 for (unsigned char bit = 0; bit < 8; bit++) {
51 bool is_one = byte & (1 << (7 - bit));
52 // using something like wait_ns(is_one ? T1L : T0L) here throws off timings
53 if (is_one) {
54 // 1
55 writePinHigh(RGB_DI_PIN);
56 wait_ns(T1H);
57 writePinLow(RGB_DI_PIN);
58 wait_ns(T1L);
59 } else {
60 // 0
61 writePinHigh(RGB_DI_PIN);
62 wait_ns(T0H);
63 writePinLow(RGB_DI_PIN);
64 wait_ns(T0L);
65 }
66 }
67}
68
69void ws2812_init(void) { setPinOutput(RGB_DI_PIN); }
70
71// Setleds for standard RGB
72void ws2812_setleds(LED_TYPE *ledarray, uint16_t leds) {
73 static bool s_init = false;
74 if (!s_init) {
75 ws2812_init();
76 s_init = true;
77 }
78
79 // this code is very time dependent, so we need to disable interrupts
80 chSysLock();
81
82 for (uint8_t i = 0; i < leds; i++) {
83 // WS2812 protocol dictates grb order
84 sendByte(ledarray[i].g);
85 sendByte(ledarray[i].r);
86 sendByte(ledarray[i].b);
87 }
88
89 wait_ns(RES);
90
91 chSysUnlock();
92}
93
94// Setleds for SK6812RGBW
95void ws2812_setleds_rgbw(LED_TYPE *ledarray, uint16_t leds) {
96// not supported - for now error out if its enabled
97#ifdef RGBW
98# error "RGBW not supported"
99#endif
100}
diff --git a/drivers/arm/ws2812.h b/drivers/arm/ws2812.h
new file mode 100644
index 000000000..bf5c9fd0f
--- /dev/null
+++ b/drivers/arm/ws2812.h
@@ -0,0 +1,17 @@
1#pragma once
2
3#include "quantum/color.h"
4
5/* User Interface
6 *
7 * Input:
8 * ledarray: An array of GRB data describing the LED colors
9 * number_of_leds: The number of LEDs to write
10 *
11 * The functions will perform the following actions:
12 * - Set the data-out pin as output
13 * - Send out the LED data
14 * - Wait 50�s to reset the LEDs
15 */
16void ws2812_setleds(LED_TYPE *ledarray, uint16_t number_of_leds);
17void ws2812_setleds_rgbw(LED_TYPE *ledarray, uint16_t number_of_leds);
diff --git a/keyboards/handwired/onekey/bluepill/config.h b/keyboards/handwired/onekey/bluepill/config.h
index 81282ae1f..01555e431 100644
--- a/keyboards/handwired/onekey/bluepill/config.h
+++ b/keyboards/handwired/onekey/bluepill/config.h
@@ -25,3 +25,5 @@
25#define BACKLIGHT_PIN A0 25#define BACKLIGHT_PIN A0
26#define BACKLIGHT_PWM_DRIVER PWMD2 26#define BACKLIGHT_PWM_DRIVER PWMD2
27#define BACKLIGHT_PWM_CHANNEL 1 27#define BACKLIGHT_PWM_CHANNEL 1
28
29#define RGB_DI_PIN A1
diff --git a/keyboards/handwired/onekey/keymaps/rgb/config.h b/keyboards/handwired/onekey/keymaps/rgb/config.h
new file mode 100644
index 000000000..89e76326b
--- /dev/null
+++ b/keyboards/handwired/onekey/keymaps/rgb/config.h
@@ -0,0 +1,4 @@
1#pragma once
2
3#define RGBLED_NUM 9
4#define RGBLIGHT_ANIMATIONS
diff --git a/keyboards/handwired/onekey/keymaps/rgb/keymap.c b/keyboards/handwired/onekey/keymaps/rgb/keymap.c
new file mode 100644
index 000000000..a96c6f386
--- /dev/null
+++ b/keyboards/handwired/onekey/keymaps/rgb/keymap.c
@@ -0,0 +1,11 @@
1#include QMK_KEYBOARD_H
2
3const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
4 LAYOUT( RGB_MOD )
5};
6
7void keyboard_post_init_user(void) {
8 rgblight_enable_noeeprom();
9 rgblight_sethsv_noeeprom_cyan();
10 rgblight_mode_noeeprom(RGBLIGHT_MODE_RAINBOW_SWIRL);
11}
diff --git a/keyboards/handwired/onekey/keymaps/rgb/rules.mk b/keyboards/handwired/onekey/keymaps/rgb/rules.mk
new file mode 100644
index 000000000..1e3cebb14
--- /dev/null
+++ b/keyboards/handwired/onekey/keymaps/rgb/rules.mk
@@ -0,0 +1 @@
RGBLIGHT_ENABLE = yes
diff --git a/keyboards/handwired/onekey/proton_c/config.h b/keyboards/handwired/onekey/proton_c/config.h
index d4fb9c829..fe34f94ad 100644
--- a/keyboards/handwired/onekey/proton_c/config.h
+++ b/keyboards/handwired/onekey/proton_c/config.h
@@ -26,3 +26,5 @@
26#define BACKLIGHT_PWM_DRIVER PWMD4 26#define BACKLIGHT_PWM_DRIVER PWMD4
27#define BACKLIGHT_PWM_CHANNEL 3 27#define BACKLIGHT_PWM_CHANNEL 3
28#define BACKLIGHT_PAL_MODE 2 28#define BACKLIGHT_PAL_MODE 2
29
30#define RGB_DI_PIN A1
diff --git a/keyboards/handwired/onekey/stm32f0_disco/config.h b/keyboards/handwired/onekey/stm32f0_disco/config.h
index 4024ee1ca..637ed65d3 100644
--- a/keyboards/handwired/onekey/stm32f0_disco/config.h
+++ b/keyboards/handwired/onekey/stm32f0_disco/config.h
@@ -26,3 +26,5 @@
26#define BACKLIGHT_PWM_DRIVER PWMD3 26#define BACKLIGHT_PWM_DRIVER PWMD3
27#define BACKLIGHT_PWM_CHANNEL 3 27#define BACKLIGHT_PWM_CHANNEL 3
28#define BACKLIGHT_PAL_MODE 0 28#define BACKLIGHT_PAL_MODE 0
29
30#define RGB_DI_PIN B15
diff --git a/quantum/stm32/proton_c.mk b/quantum/stm32/proton_c.mk
index 193e09ca1..ff28a4cb5 100644
--- a/quantum/stm32/proton_c.mk
+++ b/quantum/stm32/proton_c.mk
@@ -2,7 +2,7 @@
2 2
3# These are defaults based on what has been implemented for ARM boards 3# These are defaults based on what has been implemented for ARM boards
4AUDIO_ENABLE = yes 4AUDIO_ENABLE = yes
5RGBLIGHT_ENABLE = no 5WS2812_DRIVER = bitbang
6 6
7# Force task driven PWM until ARM can provide automatic configuration 7# Force task driven PWM until ARM can provide automatic configuration
8ifneq ($(strip $(BACKLIGHT_ENABLE)), no) 8ifneq ($(strip $(BACKLIGHT_ENABLE)), no)
diff --git a/tmk_core/protocol/chibios/main.c b/tmk_core/protocol/chibios/main.c
index de2b493b8..c304f4d79 100644
--- a/tmk_core/protocol/chibios/main.c
+++ b/tmk_core/protocol/chibios/main.c
@@ -32,6 +32,11 @@
32#include "sendchar.h" 32#include "sendchar.h"
33#include "debug.h" 33#include "debug.h"
34#include "printf.h" 34#include "printf.h"
35#include "rgblight_reconfig.h"
36
37#if (defined(RGB_MIDI) || defined(RGBLIGHT_ANIMATIONS)) && defined(RGBLIGHT_ENABLE)
38# include "rgblight.h"
39#endif
35#ifdef SLEEP_LED_ENABLE 40#ifdef SLEEP_LED_ENABLE
36# include "sleep_led.h" 41# include "sleep_led.h"
37#endif 42#endif
@@ -215,5 +220,8 @@ int main(void) {
215#ifdef RAW_ENABLE 220#ifdef RAW_ENABLE
216 raw_hid_task(); 221 raw_hid_task();
217#endif 222#endif
223#if defined(RGBLIGHT_ANIMATIONS) && defined(RGBLIGHT_ENABLE)
224 rgblight_task();
225#endif
218 } 226 }
219} 227}