forked from qmk/qmk_firmware
-
Notifications
You must be signed in to change notification settings - Fork 412
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* ARM - ws2812 bitbang (qmk#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 * Support RGBLIGHT_SLEEP when ChibiOS boards suspend (qmk#7280) Copypasta from the AVR suspend implementation with a Teensy-specific hack removed * Unify RGB and RGBW commands (qmk#7297) * Fix unicode in comments Co-Authored-By: fauxpark <[email protected]> * Remove separate RGBW implementation for a unified function * Set White to 0 in RGBW LEDs This is just to get this working, later, proper brightness can be handled elsewhere. * Use us instead of nanoseconds(?) since it renders correctly on web * Remove RGBW function from arm/ws2812.h * Remove RGBW function from arm/ws2812.c * Formatting changes * Add doc info * Remove force of debug on within rgblight - causes lockups waiting for hid_listen (qmk#7330) * Move Ergodox EZ RGB Light code to custom driver (qmk#7309) * Move Ergodox EZ RGB code to custom driver Also implements full addressing of Ergodox EZ's LED Strip, as written by seebs Co-authored-by: Seebs <[email protected]> * Make Clipping range accessible for custom drivers * Remove RGBW_BB_TWI from driver and docs * Revert changes to clipping range support * Use just rgblight_set instead of full custom driver * Convert to i2c_master commands * Rename rgblight driver and clean up includes * Use White channel on RGBW LEDs * SPI DMA based RGB Underglow for STM32 (qmk#7674) * Initial stash of ws2812 spi driver * Update comment, add sync backup plan * Add testing notes to spi ws2812 driver * Align RGBW error messages Co-authored-by: Joel Challis <[email protected]> Co-authored-by: Jonathan Rascher <[email protected]> Co-authored-by: Florian Didron <[email protected]>
- Loading branch information
1 parent
81126b6
commit df91396
Showing
17 changed files
with
426 additions
and
164 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,95 @@ | ||
#error("NOT SUPPORTED") | ||
#include "quantum.h" | ||
#include "ws2812.h" | ||
#include "ch.h" | ||
#include "hal.h" | ||
|
||
/* Adapted from https://github.com/bigjosh/SimpleNeoPixelDemo/ */ | ||
|
||
#ifndef NOP_FUDGE | ||
# if defined(STM32F1XX) || defined(STM32F1xx) || defined(STM32F0XX) || defined(STM32F0xx) || defined(STM32F3XX) || defined(STM32F3xx) || defined(STM32L0XX) || defined(STM32L0xx) | ||
# define NOP_FUDGE 0.4 | ||
# 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 6 | ||
#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" \ | ||
"nop\n\t" \ | ||
"nop\n\t" \ | ||
"nop\n\t"); \ | ||
} \ | ||
} while (0) | ||
|
||
// These are the timing constraints taken mostly from the WS2812 datasheets | ||
// These are chosen to be conservative and avoid problems rather than for maximum throughput | ||
|
||
#define T1H 900 // Width of a 1 bit in ns | ||
#define T1L (1250 - T1H) // Width of a 1 bit in ns | ||
|
||
#define T0H 350 // Width of a 0 bit in ns | ||
#define T0L (1250 - T0H) // Width of a 0 bit in ns | ||
|
||
// The reset gap can be 6000 ns, but depending on the LED strip it may have to be increased | ||
// to values like 600000 ns. If it is too small, the pixels will show nothing most of the time. | ||
#define RES 10000 // Width of the low gap between bits to cause a frame to latch | ||
|
||
void sendByte(uint8_t byte) { | ||
// WS2812 protocol wants most significant bits first | ||
for (unsigned char bit = 0; bit < 8; bit++) { | ||
bool is_one = byte & (1 << (7 - bit)); | ||
// using something like wait_ns(is_one ? T1L : T0L) here throws off timings | ||
if (is_one) { | ||
// 1 | ||
writePinHigh(RGB_DI_PIN); | ||
wait_ns(T1H); | ||
writePinLow(RGB_DI_PIN); | ||
wait_ns(T1L); | ||
} else { | ||
// 0 | ||
writePinHigh(RGB_DI_PIN); | ||
wait_ns(T0H); | ||
writePinLow(RGB_DI_PIN); | ||
wait_ns(T0L); | ||
} | ||
} | ||
} | ||
|
||
void ws2812_init(void) { setPinOutput(RGB_DI_PIN); } | ||
|
||
// Setleds for standard RGB | ||
void ws2812_setleds(LED_TYPE *ledarray, uint16_t leds) { | ||
static bool s_init = false; | ||
if (!s_init) { | ||
ws2812_init(); | ||
s_init = true; | ||
} | ||
|
||
// this code is very time dependent, so we need to disable interrupts | ||
chSysLock(); | ||
|
||
for (uint8_t i = 0; i < leds; i++) { | ||
// WS2812 protocol dictates grb order | ||
sendByte(ledarray[i].g); | ||
sendByte(ledarray[i].r); | ||
sendByte(ledarray[i].b); | ||
#ifdef RGBW | ||
sendByte(ledarray[i].w); | ||
#endif | ||
} | ||
|
||
wait_ns(RES); | ||
|
||
chSysUnlock(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#pragma once | ||
|
||
#include "quantum/color.h" | ||
|
||
/* User Interface | ||
* | ||
* Input: | ||
* ledarray: An array of GRB data describing the LED colors | ||
* number_of_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 50us to reset the LEDs | ||
*/ | ||
void ws2812_setleds(LED_TYPE *ledarray, uint16_t number_of_leds); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,90 @@ | ||
#error("NOT SUPPORTED") | ||
#include "quantum.h" | ||
#include "ws2812.h" | ||
|
||
/* Adapted from https://github.com/gamazeps/ws2812b-chibios-SPIDMA/ */ | ||
|
||
#ifdef RGBW | ||
# error "RGBW not supported" | ||
#endif | ||
|
||
// Define the spi your LEDs are plugged to here | ||
#ifndef WS2812_SPI | ||
# define WS2812_SPI SPID1 | ||
#endif | ||
|
||
#ifndef WS2812_SPI_MOSI_PAL_MODE | ||
# define WS2812_SPI_MOSI_PAL_MODE 5 | ||
#endif | ||
|
||
#define BYTES_FOR_LED_BYTE 4 | ||
#define NB_COLORS 3 | ||
#define BYTES_FOR_LED (BYTES_FOR_LED_BYTE * NB_COLORS) | ||
#define DATA_SIZE (BYTES_FOR_LED * RGBLED_NUM) | ||
#define RESET_SIZE 200 | ||
#define PREAMBLE_SIZE 4 | ||
|
||
static uint8_t txbuf[PREAMBLE_SIZE + DATA_SIZE + RESET_SIZE] = {0}; | ||
|
||
/* | ||
* As the trick here is to use the SPI to send a huge pattern of 0 and 1 to | ||
* the ws2812b protocol, we use this helper function to translate bytes into | ||
* 0s and 1s for the LED (with the appropriate timing). | ||
*/ | ||
static uint8_t get_protocol_eq(uint8_t data, int pos) { | ||
uint8_t eq = 0; | ||
if (data & (1 << (2 * (3 - pos)))) | ||
eq = 0b1110; | ||
else | ||
eq = 0b1000; | ||
if (data & (2 << (2 * (3 - pos)))) | ||
eq += 0b11100000; | ||
else | ||
eq += 0b10000000; | ||
return eq; | ||
} | ||
|
||
static void set_led_color_rgb(LED_TYPE color, int pos) { | ||
uint8_t* tx_start = &txbuf[PREAMBLE_SIZE]; | ||
|
||
for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + j] = get_protocol_eq(color.g, j); | ||
for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE + j] = get_protocol_eq(color.r, j); | ||
for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE * 2 + j] = get_protocol_eq(color.b, j); | ||
} | ||
|
||
void ws2812_init(void) { | ||
#if defined(USE_GPIOV1) | ||
palSetLineMode(RGB_DI_PIN, PAL_MODE_STM32_ALTERNATE_PUSHPULL); | ||
#else | ||
palSetLineMode(RGB_DI_PIN, PAL_MODE_ALTERNATE(WS2812_SPI_MOSI_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL); | ||
#endif | ||
|
||
// TODO: more dynamic baudrate | ||
static const SPIConfig spicfg = { | ||
NULL, PAL_PORT(RGB_DI_PIN), PAL_PAD(RGB_DI_PIN), | ||
SPI_CR1_BR_1 | SPI_CR1_BR_0 // baudrate : fpclk / 8 => 1tick is 0.32us (2.25 MHz) | ||
}; | ||
|
||
spiAcquireBus(&WS2812_SPI); /* Acquire ownership of the bus. */ | ||
spiStart(&WS2812_SPI, &spicfg); /* Setup transfer parameters. */ | ||
spiSelect(&WS2812_SPI); /* Slave Select assertion. */ | ||
} | ||
|
||
void ws2812_setleds(LED_TYPE* ledarray, uint16_t leds) { | ||
static bool s_init = false; | ||
if (!s_init) { | ||
ws2812_init(); | ||
s_init = true; | ||
} | ||
|
||
for (uint8_t i = 0; i < leds; i++) { | ||
set_led_color_rgb(ledarray[i], i); | ||
} | ||
|
||
// Send async - each led takes ~0.03ms, 50 leds ~1.5ms, animations flushing faster than send will cause issues. | ||
// Instead spiSend can be used to send synchronously (or the thread logic can be added back). | ||
#ifdef WS2812_SPI_SYNC | ||
spiSend(&WS2812_SPI, sizeof(txbuf) / sizeof(txbuf[0]), txbuf); | ||
#else | ||
spiStartSend(&WS2812_SPI, sizeof(txbuf) / sizeof(txbuf[0]), txbuf); | ||
#endif | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.