From f860922d67efaa614ffa5ba0ac904984098a467d Mon Sep 17 00:00:00 2001 From: Scott Lawson Date: Fri, 30 Dec 2016 22:31:27 -0700 Subject: [PATCH] Removed ws2812b i2s library dependency, updated README I have added a pre-configured version of the ws2812b i2s library to the Arduino code. This removes the need to download and install the ws2812b i2s library manually. The ws2812b code has been preconfigured to reduce the temporal compared to the default value. The default value was found to cause excessive flickering. The readme has been updated to reflect this change. Also added a note about the maximum number of LEDs (255) --- README.md | 9 +- arduino/ws2812_controller/ws2812.h | 26 +++ .../ws2812_controller/ws2812_controller.ino | 5 +- arduino/ws2812_controller/ws2812_defs.h | 172 ++++++++++++++++++ arduino/ws2812_controller/ws2812_dma.c | 102 +++++++++++ arduino/ws2812_controller/ws2812_dma.h | 25 +++ arduino/ws2812_controller/ws2812_gamma.cpp | 165 +++++++++++++++++ arduino/ws2812_controller/ws2812_gamma.h | 12 ++ arduino/ws2812_controller/ws2812_i2s.cpp | 169 +++++++++++++++++ arduino/ws2812_controller/ws2812_i2s.h | 41 +++++ 10 files changed, 721 insertions(+), 5 deletions(-) create mode 100644 arduino/ws2812_controller/ws2812.h create mode 100644 arduino/ws2812_controller/ws2812_defs.h create mode 100644 arduino/ws2812_controller/ws2812_dma.c create mode 100644 arduino/ws2812_controller/ws2812_dma.h create mode 100644 arduino/ws2812_controller/ws2812_gamma.cpp create mode 100644 arduino/ws2812_controller/ws2812_gamma.h create mode 100644 arduino/ws2812_controller/ws2812_i2s.cpp create mode 100644 arduino/ws2812_controller/ws2812_i2s.h diff --git a/README.md b/README.md index 76bd1c9..0aa7e94 100644 --- a/README.md +++ b/README.md @@ -63,10 +63,10 @@ If `pip` is not found try using `python -m pip install` instead. ## Arduino dependencies ESP8266 firmare is uploaded using the Arduino IDE. See [this tutorial](https://learn.sparkfun.com/tutorials/esp8266-thing-hookup-guide/installing-the-esp8266-arduino-addon) to setup the Arduino IDE for ESP8266. -This [ws2812b i2s library](https://github.com/JoDaNl/esp8266_ws2812_i2s) must be downloaded and installed in the Arduino libraries folder. - + # Hardware Connections -The ESP8266 has hardware support for [I²S](https://en.wikipedia.org/wiki/I%C2%B2S) and this peripheral is used by the [ws2812b i2s library](https://github.com/JoDaNl/esp8266_ws2812_i2s) to control the ws2812b LED strip. This signficantly improves performance compared to bit-banging the IO pin. Unfortunately, this means that the LED strip **must** be connected to the RX1 pin, which is not accessible in some ESP8266 modules (such as the ESP-01). +The ESP8266 has hardware support for [I²S](https://en.wikipedia.org/wiki/I%C2%B2S) and this peripheral is used to control the ws2812b LED strip. This signficantly improves performance compared to bit-banging the IO pin. Unfortunately, this means that the LED strip **must** be connected to the RX1 pin, which is not accessible in some ESP8266 modules (such as the ESP-01). The RX1 pin on the ESP8266 module should be connected to the data input pin of the ws2812b LED strip (often labelled DIN or D0). @@ -99,5 +99,8 @@ A PyQtGraph GUI will open to display the output of the visualization on the comp If you encounter any issues or have questions about this project, feel free to open a new issue. +# Limitations +The visualization code currently supports up to 255 LEDs. Support for additional LEDs will be added in the near future. + # License All code in this project is released under the MIT License. \ No newline at end of file diff --git a/arduino/ws2812_controller/ws2812.h b/arduino/ws2812_controller/ws2812.h new file mode 100644 index 0000000..5085988 --- /dev/null +++ b/arduino/ws2812_controller/ws2812.h @@ -0,0 +1,26 @@ +// ws2812.h + +#ifndef __WS2812_H__ +#define __WS2812_H__ + +// Gamma Correction +// Uses a nonlinear lookup table to correct for human perception of light. +// When gamma correction is used, a brightness value of 2X should appear twice +// as bright as a value of X. +// 1 = Enable gamma correction +// 0 = Disable gamma correction +// Note: There seems to be a bug and you can't actually disable this +#define WS2812_GAMMA_CORRECTION (0) + +// Temporal Dithering +// Dithering preserves color and light when brightness is low. +// Sometimes this can cause undesirable flickering. +// 1 = Disable temporal dithering +// 2, 6, 8 = Enable temporal dithering (larger values = more dithering) +#define WS2812_DITHER_NUM (4) + +#define WS2812_USE_INTERRUPT (0) // not supported yet + +#endif + +// end of file diff --git a/arduino/ws2812_controller/ws2812_controller.ino b/arduino/ws2812_controller/ws2812_controller.ino index 1632d1b..fa79bd7 100644 --- a/arduino/ws2812_controller/ws2812_controller.ino +++ b/arduino/ws2812_controller/ws2812_controller.ino @@ -3,10 +3,11 @@ #include #include #include -#include +#include "ws2812_i2s.h" // Set this to the number of LEDs in your LED strip -#define NUM_LEDS 260 +#define NUM_LEDS 60 +// Maximum number of packets to hold in the buffer. Don't change this. #define BUFFER_LEN 1024 // Wifi and socket settings diff --git a/arduino/ws2812_controller/ws2812_defs.h b/arduino/ws2812_controller/ws2812_defs.h new file mode 100644 index 0000000..6a4a08d --- /dev/null +++ b/arduino/ws2812_controller/ws2812_defs.h @@ -0,0 +1,172 @@ +// w2812_defs.h +// +// contains material from Charles Lohr, but changed by me. + +#ifndef __WS2812_I2S_DEFS_H__ +#define __WS2812_I2S_DEFS_H__ + +#include + +// include file from project folder +#include "ws2812.h" + +// ----------------------------------------------------- + +// Helper macro's + +#define NUM_RGB_BYTES (num_leds * 3) +#define NUM_I2S_PIXEL_BYTES (num_leds * 3 * 4) // (#leds) * (RGB) * (4 i2s bits) +#define NUM_I2S_PIXEL_WORDS (num_leds * 3) + +// ----------------------------------------------------- + +// I2S timing parameters + +// Creates an I2S SR of 93,750 Hz, or 3 MHz Bitclock (.333us/sample) +// Measured on scope : 4 bitclock-ticks every 1200ns --> 300ns bitclock ??? +// 12000000L/(div*bestbck*2) + +#define WS_I2S_BCK (17) +#define WS_I2S_DIV (4) +#define NUM_I2S_ZERO_BYTES (28) // WS2812 LED Treset = 67us (must be >50us) +#define NUM_I2S_ZERO_WORDS (NUM_I2S_ZERO_BYTES / 4) + +// ----------------------------------------------------- + +#ifndef i2c_bbpll +#define i2c_bbpll 0x67 +#define i2c_bbpll_en_audio_clock_out 4 +#define i2c_bbpll_en_audio_clock_out_msb 7 +#define i2c_bbpll_en_audio_clock_out_lsb 7 +#define i2c_bbpll_hostid 4 +#endif + +// ----------------------------------------------------- + +#define i2c_writeReg_Mask(block, host_id, reg_add, Msb, Lsb, indata) rom_i2c_writeReg_Mask(block, host_id, reg_add, Msb, Lsb, indata) +#define i2c_readReg_Mask(block, host_id, reg_add, Msb, Lsb) rom_i2c_readReg_Mask(block, host_id, reg_add, Msb, Lsb) +#define i2c_writeReg_Mask_def(block, reg_add, indata) i2c_writeReg_Mask(block, block##_hostid, reg_add, reg_add##_msb, reg_add##_lsb, indata) +#define i2c_readReg_Mask_def(block, reg_add) i2c_readReg_Mask(block, block##_hostid, reg_add, reg_add##_msb, reg_add##_lsb) + +// ----------------------------------------------------- + +#ifndef ETS_SLC_INUM +#define ETS_SLC_INUM 1 +#endif + +// ----------------------------------------------------- + +// from i2s_reg.h + +#define DR_REG_I2S_BASE (0x60000e00) + +#define I2STXFIFO (DR_REG_I2S_BASE + 0x0000) +#define I2SRXFIFO (DR_REG_I2S_BASE + 0x0004) +#define I2SCONF (DR_REG_I2S_BASE + 0x0008) +#define I2S_BCK_DIV_NUM 0x0000003F +#define I2S_BCK_DIV_NUM_S 22 +#define I2S_CLKM_DIV_NUM 0x0000003F +#define I2S_CLKM_DIV_NUM_S 16 +#define I2S_BITS_MOD 0x0000000F +#define I2S_BITS_MOD_S 12 +#define I2S_RECE_MSB_SHIFT (BIT(11)) +#define I2S_TRANS_MSB_SHIFT (BIT(10)) +#define I2S_I2S_RX_START (BIT(9)) +#define I2S_I2S_TX_START (BIT(8)) +#define I2S_MSB_RIGHT (BIT(7)) +#define I2S_RIGHT_FIRST (BIT(6)) +#define I2S_RECE_SLAVE_MOD (BIT(5)) +#define I2S_TRANS_SLAVE_MOD (BIT(4)) +#define I2S_I2S_RX_FIFO_RESET (BIT(3)) +#define I2S_I2S_TX_FIFO_RESET (BIT(2)) +#define I2S_I2S_RX_RESET (BIT(1)) +#define I2S_I2S_TX_RESET (BIT(0)) +#define I2S_I2S_RESET_MASK 0xf + +#define I2SINT_RAW (DR_REG_I2S_BASE + 0x000c) +#define I2S_I2S_TX_REMPTY_INT_RAW (BIT(5)) +#define I2S_I2S_TX_WFULL_INT_RAW (BIT(4)) +#define I2S_I2S_RX_REMPTY_INT_RAW (BIT(3)) +#define I2S_I2S_RX_WFULL_INT_RAW (BIT(2)) +#define I2S_I2S_TX_PUT_DATA_INT_RAW (BIT(1)) +#define I2S_I2S_RX_TAKE_DATA_INT_RAW (BIT(0)) + +#define I2SINT_ST (DR_REG_I2S_BASE + 0x0010) +#define I2S_I2S_TX_REMPTY_INT_ST (BIT(5)) +#define I2S_I2S_TX_WFULL_INT_ST (BIT(4)) +#define I2S_I2S_RX_REMPTY_INT_ST (BIT(3)) +#define I2S_I2S_RX_WFULL_INT_ST (BIT(2)) +#define I2S_I2S_TX_PUT_DATA_INT_ST (BIT(1)) +#define I2S_I2S_RX_TAKE_DATA_INT_ST (BIT(0)) + +#define I2SINT_ENA (DR_REG_I2S_BASE + 0x0014) +#define I2S_I2S_TX_REMPTY_INT_ENA (BIT(5)) +#define I2S_I2S_TX_WFULL_INT_ENA (BIT(4)) +#define I2S_I2S_RX_REMPTY_INT_ENA (BIT(3)) +#define I2S_I2S_RX_WFULL_INT_ENA (BIT(2)) +#define I2S_I2S_TX_PUT_DATA_INT_ENA (BIT(1)) +#define I2S_I2S_RX_TAKE_DATA_INT_ENA (BIT(0)) + +#define I2SINT_CLR (DR_REG_I2S_BASE + 0x0018) +#define I2S_I2S_TX_REMPTY_INT_CLR (BIT(5)) +#define I2S_I2S_TX_WFULL_INT_CLR (BIT(4)) +#define I2S_I2S_RX_REMPTY_INT_CLR (BIT(3)) +#define I2S_I2S_RX_WFULL_INT_CLR (BIT(2)) +#define I2S_I2S_PUT_DATA_INT_CLR (BIT(1)) +#define I2S_I2S_TAKE_DATA_INT_CLR (BIT(0)) + +#define I2STIMING (DR_REG_I2S_BASE + 0x001c) +#define I2S_TRANS_BCK_IN_INV (BIT(22)) +#define I2S_RECE_DSYNC_SW (BIT(21)) +#define I2S_TRANS_DSYNC_SW (BIT(20)) +#define I2S_RECE_BCK_OUT_DELAY 0x00000003 +#define I2S_RECE_BCK_OUT_DELAY_S 18 +#define I2S_RECE_WS_OUT_DELAY 0x00000003 +#define I2S_RECE_WS_OUT_DELAY_S 16 +#define I2S_TRANS_SD_OUT_DELAY 0x00000003 +#define I2S_TRANS_SD_OUT_DELAY_S 14 +#define I2S_TRANS_WS_OUT_DELAY 0x00000003 +#define I2S_TRANS_WS_OUT_DELAY_S 12 +#define I2S_TRANS_BCK_OUT_DELAY 0x00000003 +#define I2S_TRANS_BCK_OUT_DELAY_S 10 +#define I2S_RECE_SD_IN_DELAY 0x00000003 +#define I2S_RECE_SD_IN_DELAY_S 8 +#define I2S_RECE_WS_IN_DELAY 0x00000003 +#define I2S_RECE_WS_IN_DELAY_S 6 +#define I2S_RECE_BCK_IN_DELAY 0x00000003 +#define I2S_RECE_BCK_IN_DELAY_S 4 +#define I2S_TRANS_WS_IN_DELAY 0x00000003 +#define I2S_TRANS_WS_IN_DELAY_S 2 +#define I2S_TRANS_BCK_IN_DELAY 0x00000003 +#define I2S_TRANS_BCK_IN_DELAY_S 0 + +#define I2S_FIFO_CONF (DR_REG_I2S_BASE + 0x0020) +#define I2S_I2S_RX_FIFO_MOD 0x00000007 +#define I2S_I2S_RX_FIFO_MOD_S 16 +#define I2S_I2S_TX_FIFO_MOD 0x00000007 +#define I2S_I2S_TX_FIFO_MOD_S 13 +#define I2S_I2S_DSCR_EN (BIT(12)) +#define I2S_I2S_TX_DATA_NUM 0x0000003F +#define I2S_I2S_TX_DATA_NUM_S 6 +#define I2S_I2S_RX_DATA_NUM 0x0000003F +#define I2S_I2S_RX_DATA_NUM_S 0 + +#define I2SRXEOF_NUM (DR_REG_I2S_BASE + 0x0024) +#define I2S_I2S_RX_EOF_NUM 0xFFFFFFFF +#define I2S_I2S_RX_EOF_NUM_S 0 + +#define I2SCONF_SIGLE_DATA (DR_REG_I2S_BASE + 0x0028) +#define I2S_I2S_SIGLE_DATA 0xFFFFFFFF +#define I2S_I2S_SIGLE_DATA_S 0 + +#define I2SCONF_CHAN (DR_REG_I2S_BASE + 0x002c) +#define I2S_RX_CHAN_MOD 0x00000003 +#define I2S_RX_CHAN_MOD_S 3 +#define I2S_TX_CHAN_MOD 0x00000007 +#define I2S_TX_CHAN_MOD_S 0 + +// ----------------------------------------------------- + +#endif + +// end of file diff --git a/arduino/ws2812_controller/ws2812_dma.c b/arduino/ws2812_controller/ws2812_dma.c new file mode 100644 index 0000000..d2aa497 --- /dev/null +++ b/arduino/ws2812_controller/ws2812_dma.c @@ -0,0 +1,102 @@ +// ws2812_init.c + +// C-based helper function for initilalizing +// the I2S system + +#include +#include "slc_register.h" +#include "user_interface.h" +#include "ws2812_defs.h" +#include "ws2812_dma.h" + + +#if WS2812_USE_INTERRUPT == 1 +// for debugging purposes +static volatile uint32_t interrupt_count = 0; + +static void ws2812_isr(void) +{ + //clear all intr flags + WRITE_PERI_REG(SLC_INT_CLR, 0xffffffff);//slc_intr_status); + + interrupt_count++; +} +#endif + + +void ws2812_dma(sdio_queue_t *i2s_pixels_queue) +{ + // Reset DMA + SET_PERI_REG_MASK(SLC_CONF0, SLC_RXLINK_RST); //|SLC_TXLINK_RST); + CLEAR_PERI_REG_MASK(SLC_CONF0, SLC_RXLINK_RST); //|SLC_TXLINK_RST); + + // Clear DMA int flags + SET_PERI_REG_MASK(SLC_INT_CLR, 0xffffffff); + CLEAR_PERI_REG_MASK(SLC_INT_CLR, 0xffffffff); + + // Enable and configure DMA + CLEAR_PERI_REG_MASK(SLC_CONF0,(SLC_MODE< +#include "ws2812_gamma.h" + +static const uint8_t gamma0[] = { + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, + 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, + 10, 10, 10, 11, 11, 12, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, + 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 23, 23, 24, 24, 25, + 26, 26, 27, 28, 28, 29, 30, 30, 31, 32, 32, 33, 34, 34, 35, 36, + 37, 37, 38, 39, 40, 41, 41, 42, 43, 44, 45, 45, 46, 47, 48, 49, + 50, 51, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 80, 81, + 82, 83, 84, 85, 86, 88, 89, 90, 91, 92, 94, 95, 96, 97, 98, 100, + 101, 102, 103, 105, 106, 107, 109, 110, 111, 113, 114, 115, 117, 118, 119, 121, + 122, 123, 125, 126, 128, 129, 130, 132, 133, 135, 136, 138, 139, 141, 142, 144, + 145, 147, 148, 150, 151, 153, 154, 156, 157, 159, 161, 162, 164, 165, 167, 169, + 170, 172, 173, 175, 177, 178, 180, 182, 183, 185, 187, 189, 190, 192, 194, 196, + 197, 199, 201, 203, 204, 206, 208, 210, 212, 213, 215, 217, 219, 221, 223, 225, + 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 254, 255 }; + +static const uint8_t gamma1[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, + 4, 4, 5, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, + 9, 9, 10, 10, 11, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, + 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 23, 23, 24, 24, + 25, 26, 26, 27, 28, 28, 29, 30, 30, 31, 32, 32, 33, 34, 35, 35, + 36, 37, 38, 38, 39, 40, 41, 42, 42, 43, 44, 45, 46, 47, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 73, 74, 75, 76, 77, 78, 79, 80, + 81, 82, 84, 85, 86, 87, 88, 89, 91, 92, 93, 94, 95, 97, 98, 99, + 100, 102, 103, 104, 105, 107, 108, 109, 111, 112, 113, 115, 116, 117, 119, 120, + 121, 123, 124, 126, 127, 128, 130, 131, 133, 134, 136, 137, 139, 140, 142, 143, + 145, 146, 148, 149, 151, 152, 154, 155, 157, 158, 160, 162, 163, 165, 166, 168, + 170, 171, 173, 175, 176, 178, 180, 181, 183, 185, 186, 188, 190, 192, 193, 195, + 197, 199, 200, 202, 204, 206, 207, 209, 211, 213, 215, 217, 218, 220, 222, 224, + 226, 228, 230, 232, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255 }; + +static const uint8_t gamma2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, + 4, 5, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, + 9, 10, 10, 10, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, + 16, 17, 17, 18, 18, 19, 19, 20, 21, 21, 22, 22, 23, 24, 24, 25, + 25, 26, 27, 27, 28, 29, 29, 30, 31, 31, 32, 33, 33, 34, 35, 36, + 36, 37, 38, 39, 39, 40, 41, 42, 43, 43, 44, 45, 46, 47, 48, 49, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, + 82, 83, 84, 85, 86, 87, 88, 90, 91, 92, 93, 94, 96, 97, 98, 99, + 101, 102, 103, 104, 106, 107, 108, 110, 111, 112, 114, 115, 116, 118, 119, 120, + 122, 123, 125, 126, 127, 129, 130, 132, 133, 134, 136, 137, 139, 140, 142, 143, + 145, 146, 148, 149, 151, 152, 154, 156, 157, 159, 160, 162, 163, 165, 167, 168, + 170, 172, 173, 175, 177, 178, 180, 182, 183, 185, 187, 188, 190, 192, 194, 195, + 197, 199, 201, 202, 204, 206, 208, 210, 211, 213, 215, 217, 219, 221, 222, 224, + 226, 228, 230, 232, 234, 236, 238, 240, 241, 243, 245, 247, 249, 251, 253, 255 }; + +static const uint8_t gamma3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, + 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, + 9, 9, 10, 10, 10, 11, 11, 12, 12, 12, 13, 13, 14, 14, 15, 15, + 16, 16, 17, 17, 18, 18, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, + 25, 25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 34, 35, + 36, 37, 37, 38, 39, 40, 41, 41, 42, 43, 44, 45, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 86, 87, 88, 89, 90, 92, 93, 94, 95, 96, 98, 99, + 100, 101, 103, 104, 105, 107, 108, 109, 110, 112, 113, 114, 116, 117, 118, 120, + 121, 123, 124, 125, 127, 128, 130, 131, 133, 134, 135, 137, 138, 140, 141, 143, + 144, 146, 147, 149, 150, 152, 153, 155, 157, 158, 160, 161, 163, 165, 166, 168, + 169, 171, 173, 174, 176, 178, 179, 181, 183, 184, 186, 188, 190, 191, 193, 195, + 197, 198, 200, 202, 204, 205, 207, 209, 211, 213, 214, 216, 218, 220, 222, 224, + 226, 228, 229, 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255 }; + +static const uint8_t gamma4[] = { + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, + 4, 5, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, + 9, 10, 10, 11, 11, 11, 12, 12, 13, 13, 14, 14, 14, 15, 15, 16, + 16, 17, 17, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25, + 25, 26, 27, 27, 28, 29, 29, 30, 31, 31, 32, 33, 34, 34, 35, 36, + 37, 37, 38, 39, 40, 40, 41, 42, 43, 44, 44, 45, 46, 47, 48, 49, + 50, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 81, + 82, 83, 84, 85, 86, 87, 89, 90, 91, 92, 93, 95, 96, 97, 98, 100, + 101, 102, 103, 105, 106, 107, 108, 110, 111, 112, 114, 115, 116, 118, 119, 120, + 122, 123, 125, 126, 127, 129, 130, 132, 133, 135, 136, 138, 139, 140, 142, 143, + 145, 146, 148, 149, 151, 153, 154, 156, 157, 159, 160, 162, 164, 165, 167, 168, + 170, 172, 173, 175, 177, 178, 180, 182, 183, 185, 187, 188, 190, 192, 194, 195, + 197, 199, 201, 202, 204, 206, 208, 210, 211, 213, 215, 217, 219, 221, 223, 224, + 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 245, 247, 249, 251, 253, 255 }; + +static const uint8_t gamma5[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, + 4, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 8, 8, 9, + 9, 9, 10, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 14, 15, 15, + 16, 16, 17, 17, 18, 19, 19, 20, 20, 21, 21, 22, 23, 23, 24, 24, + 25, 26, 26, 27, 28, 28, 29, 30, 30, 31, 32, 32, 33, 34, 35, 35, + 36, 37, 38, 38, 39, 40, 41, 41, 42, 43, 44, 45, 46, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 85, 86, 87, 88, 89, 90, 92, 93, 94, 95, 97, 98, 99, + 100, 102, 103, 104, 105, 107, 108, 109, 111, 112, 113, 115, 116, 117, 119, 120, + 121, 123, 124, 126, 127, 128, 130, 131, 133, 134, 136, 137, 138, 140, 141, 143, + 144, 146, 147, 149, 151, 152, 154, 155, 157, 158, 160, 161, 163, 165, 166, 168, + 170, 171, 173, 174, 176, 178, 179, 181, 183, 185, 186, 188, 190, 191, 193, 195, + 197, 198, 200, 202, 204, 206, 207, 209, 211, 213, 215, 216, 218, 220, 222, 224, + 226, 228, 230, 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255 }; + +static const uint8_t gamma6[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, + 4, 4, 5, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, + 9, 10, 10, 10, 11, 11, 12, 12, 12, 13, 13, 14, 14, 15, 15, 16, + 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 22, 22, 23, 23, 24, 25, + 25, 26, 26, 27, 28, 28, 29, 30, 30, 31, 32, 33, 33, 34, 35, 36, + 36, 37, 38, 39, 39, 40, 41, 42, 43, 43, 44, 45, 46, 47, 48, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, + 81, 83, 84, 85, 86, 87, 88, 90, 91, 92, 93, 94, 96, 97, 98, 99, + 101, 102, 103, 104, 106, 107, 108, 109, 111, 112, 113, 115, 116, 117, 119, 120, + 122, 123, 124, 126, 127, 129, 130, 131, 133, 134, 136, 137, 139, 140, 142, 143, + 145, 146, 148, 149, 151, 152, 154, 155, 157, 159, 160, 162, 163, 165, 167, 168, + 170, 171, 173, 175, 176, 178, 180, 181, 183, 185, 186, 188, 190, 192, 193, 195, + 197, 199, 200, 202, 204, 206, 208, 209, 211, 213, 215, 217, 219, 220, 222, 224, + 226, 228, 230, 232, 234, 236, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255 }; + +static const uint8_t gamma7[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, + 4, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, + 9, 9, 9, 10, 10, 11, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, + 16, 16, 17, 17, 18, 18, 19, 19, 20, 21, 21, 22, 22, 23, 23, 24, + 25, 25, 26, 27, 27, 28, 29, 29, 30, 31, 31, 32, 33, 34, 34, 35, + 36, 37, 37, 38, 39, 40, 40, 41, 42, 43, 44, 45, 45, 46, 47, 48, + 49, 50, 51, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, + 81, 82, 83, 84, 86, 87, 88, 89, 90, 91, 93, 94, 95, 96, 98, 99, + 100, 101, 103, 104, 105, 106, 108, 109, 110, 112, 113, 114, 116, 117, 118, 120, + 121, 122, 124, 125, 127, 128, 130, 131, 132, 134, 135, 137, 138, 140, 141, 143, + 144, 146, 147, 149, 150, 152, 153, 155, 156, 158, 160, 161, 163, 164, 166, 168, + 169, 171, 173, 174, 176, 178, 179, 181, 183, 184, 186, 188, 189, 191, 193, 195, + 196, 198, 200, 202, 203, 205, 207, 209, 211, 213, 214, 216, 218, 220, 222, 224, + 226, 227, 229, 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255 }; + + +#if WS2812_DITHER_NUM == 1 + const uint8_t *gamma_dither[WS2812_DITHER_NUM] = {gamma0}; +#elif WS2812_DITHER_NUM == 2 + const uint8_t *gamma_dither[WS2812_DITHER_NUM] = {gamma0,gamma1}; +#elif WS2812_DITHER_NUM == 4 + const uint8_t *gamma_dither[WS2812_DITHER_NUM] = {gamma0,gamma1,gamma2,gamma3}; +#elif WS2812_DITHER_NUM == 8 + const uint8_t *gamma_dither[WS2812_DITHER_NUM] = {gamma0,gamma1,gamma2,gamma3,gamma4,gamma5,gamma6,gamma7}; +#else + #error Invalid WS2812_DITHER_NUM value. Allowed values are 1, 2, 4, 8 +#endif + +// end of file diff --git a/arduino/ws2812_controller/ws2812_gamma.h b/arduino/ws2812_controller/ws2812_gamma.h new file mode 100644 index 0000000..84353a2 --- /dev/null +++ b/arduino/ws2812_controller/ws2812_gamma.h @@ -0,0 +1,12 @@ +// ws2812_gamma.h + +#ifndef __WS2812_GAMMA_H__ +#define __WS2812_GAMMA_H__ + +#include +#include "ws2812.h" + +extern const uint8_t *gamma_dither[WS2812_DITHER_NUM]; + +#endif + diff --git a/arduino/ws2812_controller/ws2812_i2s.cpp b/arduino/ws2812_controller/ws2812_i2s.cpp new file mode 100644 index 0000000..c0658e7 --- /dev/null +++ b/arduino/ws2812_controller/ws2812_i2s.cpp @@ -0,0 +1,169 @@ +// ws2812_lib.cpp +// +// main library file / contains class implementation +// +// Need to give credits to Charles Lohr (https://github.com/cnlohr due +// to his work on his software for driving ws2812 led-strips using +// the i2s interface of the ESP8266. +// +// This inspired me to create an ESP8266 library for the Arduino IDE +// I've added temporal dithering & gamma-correction +// for a 'more natural' light intensity profile. +// +// No pin-definitions/mapings are required/possible as the library used the I2S +// output-pin. This pin in it's turn is shared with GPIO3 & RXD0 +// + +#include +#include +#include "ws2812_i2s.h" +#include "ws2812_defs.h" +#include "ws2812_gamma.h" + +// include C-style header +extern "C" +{ +#include "ws2812_dma.h" +}; + +// class constructor +WS2812::WS2812(void) +{ + // empty for now +} + +// class de-constructor +WS2812::~WS2812(void) +{ + // empty for now + // TODO : should implement switching of DMA +} + +// Init led-string / memory buffers etc. +void WS2812::init(uint16_t _num_leds) +{ + uint8_t i; + uint16_t j; + + num_leds = _num_leds; + + // clear zero buffer + for(j=0; j>4) & 0x0f ]; + } + } + +} + +// end of file diff --git a/arduino/ws2812_controller/ws2812_i2s.h b/arduino/ws2812_controller/ws2812_i2s.h new file mode 100644 index 0000000..e40c8ba --- /dev/null +++ b/arduino/ws2812_controller/ws2812_i2s.h @@ -0,0 +1,41 @@ +// ws2812_lib.h + +#ifndef __WS2812_I2S_H__ +#define __WS2812_I2S_H__ + +#include +#include "ws2812_defs.h" + +// include C-style header +extern "C" +{ +#include "ws2812_dma.h" +}; + +typedef struct +{ + uint8_t G; // G,R,B order is determined by WS2812B + uint8_t R; + uint8_t B; +} Pixel_t; + + +class WS2812 +{ + public: + WS2812(void); + ~WS2812(void); + void init(uint16_t num_leds); + void show(Pixel_t *); + + private: + uint16_t num_leds; + uint32_t *i2s_pixels_buffer[WS2812_DITHER_NUM]; + uint32_t i2s_zeros_buffer[NUM_I2S_ZERO_WORDS]; + sdio_queue_t i2s_zeros_queue[WS2812_DITHER_NUM]; + sdio_queue_t i2s_pixels_queue[WS2812_DITHER_NUM]; +}; + +#endif + +// end of file