From 1cf63a193be50b14ecd33ee1c6eb5e470640e084 Mon Sep 17 00:00:00 2001 From: Drashna Jaelre Date: Thu, 14 Nov 2019 12:00:51 -0800 Subject: [PATCH] Move Ergodox EZ RGB Light code to custom driver (#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 * 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 --- drivers/avr/ws2812.c | 129 +---------------------------- keyboards/ergodox_ez/config.h | 12 ++- keyboards/ergodox_ez/led_i2c.c | 86 +++++++++++++++++++ keyboards/ergodox_ez/post_config.h | 20 +++++ keyboards/ergodox_ez/rules.mk | 5 +- 5 files changed, 120 insertions(+), 132 deletions(-) create mode 100644 keyboards/ergodox_ez/led_i2c.c create mode 100644 keyboards/ergodox_ez/post_config.h diff --git a/drivers/avr/ws2812.c b/drivers/avr/ws2812.c index dc7e8d48a..82d985c20 100644 --- a/drivers/avr/ws2812.c +++ b/drivers/avr/ws2812.c @@ -36,108 +36,6 @@ void ws2812_sendarray(uint8_t *array, uint16_t length); void ws2812_sendarray_mask(uint8_t *array, uint16_t length, uint8_t pinmask); -#ifdef RGBW_BB_TWI - -// Port for the I2C -# define I2C_DDR DDRD -# define I2C_PIN PIND -# define I2C_PORT PORTD - -// Pins to be used in the bit banging -# define I2C_CLK 0 -# define I2C_DAT 1 - -# define I2C_DATA_HI() \ - I2C_DDR &= ~(1 << I2C_DAT); \ - I2C_PORT |= (1 << I2C_DAT); -# define I2C_DATA_LO() \ - I2C_DDR |= (1 << I2C_DAT); \ - I2C_PORT &= ~(1 << I2C_DAT); - -# define I2C_CLOCK_HI() \ - I2C_DDR &= ~(1 << I2C_CLK); \ - I2C_PORT |= (1 << I2C_CLK); -# define I2C_CLOCK_LO() \ - I2C_DDR |= (1 << I2C_CLK); \ - I2C_PORT &= ~(1 << I2C_CLK); - -# define I2C_DELAY 1 - -void I2C_WriteBit(unsigned char c) { - if (c > 0) { - I2C_DATA_HI(); - } else { - I2C_DATA_LO(); - } - - I2C_CLOCK_HI(); - _delay_us(I2C_DELAY); - - I2C_CLOCK_LO(); - _delay_us(I2C_DELAY); - - if (c > 0) { - I2C_DATA_LO(); - } - - _delay_us(I2C_DELAY); -} - -// Inits bitbanging port, must be called before using the functions below -// -void I2C_Init(void) { - I2C_PORT &= ~((1 << I2C_DAT) | (1 << I2C_CLK)); - - I2C_CLOCK_HI(); - I2C_DATA_HI(); - - _delay_us(I2C_DELAY); -} - -// Send a START Condition -// -void I2C_Start(void) { - // set both to high at the same time - I2C_DDR &= ~((1 << I2C_DAT) | (1 << I2C_CLK)); - _delay_us(I2C_DELAY); - - I2C_DATA_LO(); - _delay_us(I2C_DELAY); - - I2C_CLOCK_LO(); - _delay_us(I2C_DELAY); -} - -// Send a STOP Condition -// -void I2C_Stop(void) { - I2C_CLOCK_HI(); - _delay_us(I2C_DELAY); - - I2C_DATA_HI(); - _delay_us(I2C_DELAY); -} - -// write a byte to the I2C slave device -// -unsigned char I2C_Write(unsigned char c) { - for (char i = 0; i < 8; i++) { - I2C_WriteBit(c & 128); - - c <<= 1; - } - - I2C_WriteBit(0); - _delay_us(I2C_DELAY); - _delay_us(I2C_DELAY); - - // _delay_us(I2C_DELAY); - // return I2C_ReadBit(); - return 0; -} - -#endif - // Setleds for standard RGB void inline ws2812_setleds(LED_TYPE *ledarray, uint16_t leds) { // ws2812_setleds_pin(ledarray,leds, _BV(ws2812_pin)); @@ -145,38 +43,15 @@ void inline ws2812_setleds(LED_TYPE *ledarray, uint16_t leds) { } void inline ws2812_setleds_pin(LED_TYPE *ledarray, uint16_t leds, uint8_t pinmask) { -#ifdef RGBW_BB_TWI - uint8_t sreg_prev, twcr_prev; - sreg_prev = SREG; - twcr_prev = TWCR; - cli(); - TWCR &= ~(1 << TWEN); - I2C_Init(); - I2C_Start(); - I2C_Write(0x84); - uint16_t datlen = leds << 2; - uint8_t curbyte; - uint8_t *data = (uint8_t *)ledarray; - while (datlen--) { - curbyte = *data++; - I2C_Write(curbyte); - } - I2C_Stop(); - SREG = sreg_prev; - TWCR = twcr_prev; -#endif - // ws2812_DDRREG |= pinmask; // Enable DDR // new universal format (DDR) _SFR_IO8((RGB_DI_PIN >> 4) + 1) |= pinmask; ws2812_sendarray_mask((uint8_t *)ledarray, leds * sizeof(LED_TYPE), pinmask); -#ifndef RGBW_BB_TWI -# ifdef RGBW +#ifdef RGBW _delay_us(80); -# else +#else _delay_us(50); -# endif #endif } diff --git a/keyboards/ergodox_ez/config.h b/keyboards/ergodox_ez/config.h index bb51ec321..e60101e5e 100644 --- a/keyboards/ergodox_ez/config.h +++ b/keyboards/ergodox_ez/config.h @@ -75,17 +75,21 @@ along with this program. If not, see . /* ws2812 RGB LED */ #define RGB_DI_PIN D7 #define RGBLIGHT_ANIMATIONS -#define RGBLED_NUM 15 // Number of LEDs #define RGBLIGHT_HUE_STEP 12 #define RGBLIGHT_SAT_STEP 255 #define RGBLIGHT_VAL_STEP 12 +// Pick one of the modes +// Defaults to 15 mirror, for legacy behavior + +// #define ERGODOX_LED_15 // Addresses 15 LEDs, but same position on both halves +// #define ERGODOX_LED_15_MIRROR // Addresses 15 LEDs, but are mirrored +// #define ERGODOX_LED_30 // Addresses all 30 LED individually + /* fix space cadet rollover issue */ #define DISABLE_SPACE_CADET_ROLLOVER -#define RGBW_BB_TWI - -#define RGBW 1 +#define RGBW #define RGBLIGHT_SLEEP diff --git a/keyboards/ergodox_ez/led_i2c.c b/keyboards/ergodox_ez/led_i2c.c new file mode 100644 index 000000000..3e75a8cd0 --- /dev/null +++ b/keyboards/ergodox_ez/led_i2c.c @@ -0,0 +1,86 @@ +/* + * light weight WS2812 lib V2.0b + * + * Controls WS2811/WS2812/WS2812B RGB-LEDs + * Author: Tim (cpldcpu@gmail.com) + * + * Jan 18th, 2014 v2.0b Initial Version + * Nov 29th, 2015 v2.3 Added SK6812RGBW support + * + * 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 . + */ +#ifdef RGBLIGHT_ENABLE + +# include "ws2812.c" +# include "ergodox_ez.h" + +extern rgblight_config_t rgblight_config; + +/* + * Forward declare internal functions + * + * The functions take a byte-array and send to the data output as WS2812 bitstream. + * The length is the number of bytes to send - three per LED. + */ + +void ws2812_sendarray(uint8_t *array, uint16_t length); +void ws2812_sendarray_mask(uint8_t *array, uint16_t length, uint8_t pinmask); + + + + +void rgblight_set(void) { + if (!rgblight_config.enable) { + for (uint8_t i = 0; i < RGBLED_NUM; i++) { + led[i].r = 0; + led[i].g = 0; + led[i].b = 0; +#ifdef RGBW + led[i].w = 0; +#endif + } + } + + + uint8_t led_num = RGBLED_NUM; + i2c_init(); + i2c_start(0x84, ERGODOX_EZ_I2C_TIMEOUT); + int i = 0; +# if defined(ERGODOX_LED_30) + // prevent right-half code from trying to bitbang all 30 + // so with 30 LEDs, we count from 29 to 15 here, and the + // other half does 0 to 14. + led_num = RGBLED_NUM / 2; + for (i = led_num + led_num - 1; i >= led_num; --i) +# elif defined(ERGODOX_LED_15_MIRROR) + for (i = 0; i < led_num; ++i) +# else // ERGDOX_LED_15 non-mirrored + for (i = led_num - 1; i >= 0; --i) +# endif + { + uint8_t *data = (uint8_t *)(led + i); + i2c_write(*data++, ERGODOX_EZ_I2C_TIMEOUT); + i2c_write(*data++, ERGODOX_EZ_I2C_TIMEOUT); + i2c_write(*data++, ERGODOX_EZ_I2C_TIMEOUT); +#ifdef RGBW + i2c_write(*data++, ERGODOX_EZ_I2C_TIMEOUT); +#endif + } + i2c_stop(); + + ws2812_setleds(led, RGBLED_NUM); +} + + +#endif // RGBLIGHT_ENABLE diff --git a/keyboards/ergodox_ez/post_config.h b/keyboards/ergodox_ez/post_config.h new file mode 100644 index 000000000..526cc8c41 --- /dev/null +++ b/keyboards/ergodox_ez/post_config.h @@ -0,0 +1,20 @@ +#pragma once + +#if !defined(ERGODOX_LED_15) && !defined(ERGODOX_LED_30) +// if no value is defined, assume previous behavior +// # define ERGODOX_LED_15 +// # define ERGODOX_LED_30 +# define ERGODOX_LED_15_MIRROR +#endif + +#if (defined(ERGODOX_LED_30) + defined(ERGODOX_LED_15) + defined(ERGODOX_LED_15_MIRROR)) != 1 +# error "You must only define one of the ERGODOX_LED options." +#endif + +#ifdef ERGODOX_LED_30 +// If using 30 LEDs, then define that many +# define RGBLED_NUM 30 // Number of LEDs +#else +// If not, then only define 15 +# define RGBLED_NUM 15 // Number of LEDs +#endif diff --git a/keyboards/ergodox_ez/rules.mk b/keyboards/ergodox_ez/rules.mk index dbc35f683..fd8f5722d 100644 --- a/keyboards/ergodox_ez/rules.mk +++ b/keyboards/ergodox_ez/rules.mk @@ -31,11 +31,14 @@ SWAP_HANDS_ENABLE= yes # Allow swapping hands of keyboard SLEEP_LED_ENABLE = no API_SYSEX_ENABLE = no RGBLIGHT_ENABLE = yes +RGBLIGHT_CUSTOM_DRIVER = yes + RGB_MATRIX_ENABLE = no # enable later DEBOUNCE_TYPE = eager_pr # project specific files -SRC += matrix.c +SRC += matrix.c \ + led_i2c.c QUANTUM_LIB_SRC += i2c_master.c LAYOUTS = ergodox