Move Ergodox EZ RGB Light code to custom driver (#7309) 0.7.74
authorDrashna Jaelre <drashna@live.com>
Thu, 14 Nov 2019 20:00:51 +0000 (12:00 -0800)
committerGitHub <noreply@github.com>
Thu, 14 Nov 2019 20:00:51 +0000 (12:00 -0800)
* 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 <seebs@seebs.net>
* 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
keyboards/ergodox_ez/config.h
keyboards/ergodox_ez/led_i2c.c [new file with mode: 0644]
keyboards/ergodox_ez/post_config.h [new file with mode: 0644]
keyboards/ergodox_ez/rules.mk

index dc7e8d4..82d985c 100644 (file)
 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
 }
 
index bb51ec3..e60101e 100644 (file)
@@ -75,17 +75,21 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 /* 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 (file)
index 0000000..3e75a8c
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ */
+#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 (file)
index 0000000..526cc8c
--- /dev/null
@@ -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
index dbc35f6..fd8f572 100644 (file)
@@ -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