Add files via upload

Including pull request to use NeoPixelBus
This commit is contained in:
not-matt 2017-12-18 20:41:27 +00:00 committed by GitHub
parent 7507cc0be2
commit eb163b6771
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 782 additions and 0 deletions

17
ws2812.h Normal file
View File

@ -0,0 +1,17 @@
// ws2812.h
#ifndef __WS2812_H__
#define __WS2812_H__
// 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 (8)
#define WS2812_USE_INTERRUPT (0) // not supported yet
#endif
// end of file

79
ws2812_controller.ino Normal file
View File

@ -0,0 +1,79 @@
#include <Arduino.h>
#include <ESP8266WiFi.h>
//#include <WebSocketsServer.h>
//#include <Hash.h>
#include <WiFiUdp.h>
#include <NeoPixelBus.h>
// Set to the number of LEDs in your LED strip
#define NUM_LEDS 242
// Maximum number of packets to hold in the buffer. Don't change this.
#define BUFFER_LEN 726
// Toggles FPS output (1 = print FPS over serial, 0 = disable output)
#define PRINT_FPS 1
//NeoPixelBus settings
const uint8_t PixelPin = 3; // make sure to set this to the correct pin, ignored for Esp8266(set to 3 by default for DMA)
// Wifi and socket settings
const char* ssid = "ASUS_VIVOBOOK";
const char* password = "T!PT)Psecret";
unsigned int localPort = 7778;
byte packetBuffer[BUFFER_LEN];
RgbColor ledDataBuffer[NUM_LEDS];
// LED strip
NeoPixelBus<NeoGrbFeature, Neo800KbpsMethod> ledstrip(NUM_LEDS, PixelPin);
WiFiUDP port;
// Network information
// IP must match the IP in config.py
IPAddress ip(192, 168, 137, 200);
// Set gateway to your router's gateway
IPAddress gateway(192, 168, 137, 1);
IPAddress subnet(255, 255, 255, 0);
void setup() {
Serial.begin(115200);
//WiFi.config(ip, gateway, subnet);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println("");
// Connect to wifi and print the IP address over serial
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
port.begin(localPort);
ledstrip.Begin();//Begin output
ledstrip.Show();//Clear the strip for use
}
uint8_t N = 0;
#if PRINT_FPS
uint16_t fpsCounter = 0;
uint32_t secondTimer = 0;
#endif
void loop() {
// Read data over socket
int packetSize = port.parsePacket();
// If packets have been received, interpret the command
if (packetSize) {
int len = port.read(packetBuffer, BUFFER_LEN);
for(int i = 0; i < len; i+=4) {
packetBuffer[len] = 0;
N = packetBuffer[i];
RgbColor pixel((uint8_t)packetBuffer[i+1], (uint8_t)packetBuffer[i+2], (uint8_t)packetBuffer[i+3]);
ledstrip.SetPixelColor(N, pixel);
}
ledstrip.Show();
Serial.print("/");
}
}

172
ws2812_defs.h Normal file
View File

@ -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 <stdint.h>
// 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

102
ws2812_dma.c Normal file
View File

@ -0,0 +1,102 @@
// ws2812_init.c
// C-based helper function for initilalizing
// the I2S system
#include <string.h>
#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<<SLC_MODE_S));
SET_PERI_REG_MASK(SLC_CONF0,(1<<SLC_MODE_S));
SET_PERI_REG_MASK(SLC_RX_DSCR_CONF,SLC_INFOR_NO_REPLACE|SLC_TOKEN_NO_REPLACE);
CLEAR_PERI_REG_MASK(SLC_RX_DSCR_CONF, SLC_RX_FILL_EN|SLC_RX_EOF_MODE | SLC_RX_FILL_MODE);
// configure DMA descriptor
CLEAR_PERI_REG_MASK(SLC_RX_LINK,SLC_RXLINK_DESCADDR_MASK);
SET_PERI_REG_MASK(SLC_RX_LINK, ((uint32)i2s_pixels_queue) & SLC_RXLINK_DESCADDR_MASK);
#if WS2812_USE_INTERRUPT == 1
// Attach the DMA interrupt
ets_isr_attach(ETS_SLC_INUM, (int_handler_t)ws2812_isr , (void *)0);
//Enable DMA operation intr
// WRITE_PERI_REG(SLC_INT_ENA, SLC_RX_EOF_INT_ENA);
//clear any interrupt flags that are set
WRITE_PERI_REG(SLC_INT_CLR, 0xffffffff);
///enable DMA intr in cpu
ets_isr_unmask(1<<ETS_SLC_INUM);
#endif
//Start transmission
SET_PERI_REG_MASK(SLC_RX_LINK, SLC_RXLINK_START);
//Init pins to i2s functions
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_I2SO_DATA);
//Enable clock to i2s subsystem
i2c_writeReg_Mask_def(i2c_bbpll, i2c_bbpll_en_audio_clock_out, 1);
//Reset I2S subsystem
CLEAR_PERI_REG_MASK(I2SCONF,I2S_I2S_RESET_MASK);
SET_PERI_REG_MASK(I2SCONF,I2S_I2S_RESET_MASK);
CLEAR_PERI_REG_MASK(I2SCONF,I2S_I2S_RESET_MASK);
//Select 16bits per channel (FIFO_MOD=0), no DMA access (FIFO only)
CLEAR_PERI_REG_MASK(I2S_FIFO_CONF, I2S_I2S_DSCR_EN|(I2S_I2S_RX_FIFO_MOD<<I2S_I2S_RX_FIFO_MOD_S)|(I2S_I2S_TX_FIFO_MOD<<I2S_I2S_TX_FIFO_MOD_S));
//Enable DMA in i2s subsystem
SET_PERI_REG_MASK(I2S_FIFO_CONF, I2S_I2S_DSCR_EN);
//trans master&rece slave,MSB shift,right_first,msb right
CLEAR_PERI_REG_MASK(I2SCONF, I2S_TRANS_SLAVE_MOD|
(I2S_BITS_MOD<<I2S_BITS_MOD_S)|
(I2S_BCK_DIV_NUM <<I2S_BCK_DIV_NUM_S)|
(I2S_CLKM_DIV_NUM<<I2S_CLKM_DIV_NUM_S));
SET_PERI_REG_MASK(I2SCONF, I2S_RIGHT_FIRST|I2S_MSB_RIGHT|I2S_RECE_SLAVE_MOD|
I2S_RECE_MSB_SHIFT|I2S_TRANS_MSB_SHIFT|
(((WS_I2S_BCK-1)&I2S_BCK_DIV_NUM )<<I2S_BCK_DIV_NUM_S)|
(((WS_I2S_DIV-1)&I2S_CLKM_DIV_NUM)<<I2S_CLKM_DIV_NUM_S));
#if WS2812_USE_INTERRUPT == 1
//clear int
SET_PERI_REG_MASK(I2SINT_CLR, I2S_I2S_RX_WFULL_INT_CLR|I2S_I2S_PUT_DATA_INT_CLR|I2S_I2S_TAKE_DATA_INT_CLR);
CLEAR_PERI_REG_MASK(I2SINT_CLR, I2S_I2S_RX_WFULL_INT_CLR|I2S_I2S_PUT_DATA_INT_CLR|I2S_I2S_TAKE_DATA_INT_CLR);
//enable int
SET_PERI_REG_MASK(I2SINT_ENA, I2S_I2S_RX_REMPTY_INT_ENA|I2S_I2S_RX_TAKE_DATA_INT_ENA);
#endif
//Start transmission
SET_PERI_REG_MASK(I2SCONF,I2S_I2S_TX_START);
}
// end of file

25
ws2812_dma.h Normal file
View File

@ -0,0 +1,25 @@
// ws2812_dma.h
#ifndef __WS2812_DMA_H__
#define __WS2812_DMA_H__
// type definition taken from : sdio_slv.h
typedef struct
{
uint32_t blocksize:12;
uint32_t datalen:12;
uint32_t unused:5;
uint32_t sub_sof:1;
uint32_t eof:1;
uint32_t owner:1;
uint32_t buf_ptr;
uint32_t next_link_ptr;
} sdio_queue_t;
// -----------------------------------------------------
extern void ws2812_dma(sdio_queue_t *);
#endif

165
ws2812_gamma.cpp Normal file
View File

@ -0,0 +1,165 @@
// ws2812_gamma.cpp
//
// dithering tables with gamma correction
#include <stdint.h>
#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

12
ws2812_gamma.h Normal file
View File

@ -0,0 +1,12 @@
// ws2812_gamma.h
#ifndef __WS2812_GAMMA_H__
#define __WS2812_GAMMA_H__
#include <stdint.h>
#include "ws2812.h"
extern const uint8_t *gamma_dither[WS2812_DITHER_NUM];
#endif

169
ws2812_i2s.cpp Normal file
View File

@ -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 <Arduino.h>
#include <stdint.h>
#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<NUM_I2S_ZERO_WORDS; j++)
{
i2s_zeros_buffer[j] = 0;
}
// do memory allocation for i2s buffer(s)
for(i=0; i<WS2812_DITHER_NUM; i++)
{
i2s_pixels_buffer[i] = new uint32_t[NUM_I2S_PIXEL_WORDS];
// TODO : handle memory allocation error better
if (i2s_pixels_buffer[i] == 0)
{
Serial.println("WS2812_I2S : ERROR ALLOCATING MEMORY");
return;
}
for(j=0; j<NUM_I2S_PIXEL_WORDS; j++)
{
i2s_pixels_buffer[i][j] = 0;
}
}
// set-up DMA descriptors / 1 pair per dither-factor
for(i=0; i<WS2812_DITHER_NUM; i++)
{
i2s_pixels_queue[i].owner = 1;
i2s_pixels_queue[i].eof = 1;
i2s_pixels_queue[i].sub_sof = 0;
i2s_pixels_queue[i].datalen = NUM_I2S_PIXEL_BYTES; // Size in bytes
i2s_pixels_queue[i].blocksize = NUM_I2S_PIXEL_BYTES; // Size in bytes
i2s_pixels_queue[i].buf_ptr = (uint32_t)i2s_pixels_buffer[i];
i2s_pixels_queue[i].unused = 0;
i2s_pixels_queue[i].next_link_ptr = (uint32_t)&i2s_zeros_queue[i]; // always link to zeros-buffer
i2s_zeros_queue[i].owner = 1;
i2s_zeros_queue[i].eof = 1;
i2s_zeros_queue[i].sub_sof = 0;
i2s_zeros_queue[i].datalen = NUM_I2S_ZERO_BYTES; // Size in bytes)
i2s_zeros_queue[i].blocksize = NUM_I2S_ZERO_BYTES; // Size in bytes
i2s_zeros_queue[i].buf_ptr = (uint32_t)i2s_zeros_buffer;
i2s_zeros_queue[i].unused = 0;
if (i == (WS2812_DITHER_NUM-1)) // last DMA descriptor in linked list ?
{
// yes : link to first DMA descriptor
i2s_zeros_queue[i].next_link_ptr = (uint32_t)&i2s_pixels_queue[0];
}
else
{
// no : link to next DMA descriptor
i2s_zeros_queue[i].next_link_ptr = (uint32_t)&i2s_pixels_queue[i+1];
}
}
// call C based helper function
// I did not really succeed in putting the code from the helper
// funtion directly into this constructor...has something to do
// with C vs. C++
// the i2c_writeReg_Mask macro (+ others) failed.. see ws2812_defs.h
// may be I solve this later
// parameter = first entry in DMA descriptor list, i.e the descriptor list
ws2812_dma(i2s_pixels_queue);
}
// left this comment in tact....credit to Charles
// All functions below this line are Public Domain 2015 Charles Lohr.
// this code may be used by anyone in any way without restriction or limitation.
// Send out WS2812 bits with coded pulses, one nibble, then the other.
static const uint16_t bitpatterns[16] =
{
0b1000100010001000, 0b1000100010001110, 0b1000100011101000, 0b1000100011101110,
0b1000111010001000, 0b1000111010001110, 0b1000111011101000, 0b1000111011101110,
0b1110100010001000, 0b1110100010001110, 0b1110100011101000, 0b1110100011101110,
0b1110111010001000, 0b1110111010001110, 0b1110111011101000, 0b1110111011101110,
};
// display the pixels
void WS2812::show(Pixel_t *pixels)
{
uint8_t *buffer;
uint8_t pixelbyte;
uint8_t gammabyte;
uint16_t i,b;
uint16_t *i2s_ptr[WS2812_DITHER_NUM];
buffer = (uint8_t *)pixels;
// set-up pointers into the i2s-pixel-buffers
for(i=0; i<WS2812_DITHER_NUM; i++)
{
i2s_ptr[i] = (uint16_t *)i2s_pixels_buffer[i];
}
// for every pixel in the input-array
// - get the pixel value (either R,G, or B)
// - for every dithered buffer
// get the gamma-corrected output value
// - and transform into i2s nibble
for(b=0; b<NUM_RGB_BYTES; b++)
{
pixelbyte = *buffer++;
for(i=0; i<WS2812_DITHER_NUM; i++)
{
gammabyte = gamma_dither[i][pixelbyte];
*(i2s_ptr[i]++) = bitpatterns[ (gammabyte & 0x0f) ];
*(i2s_ptr[i]++) = bitpatterns[ (gammabyte>>4) & 0x0f ];
}
}
}
// end of file

41
ws2812_i2s.h Normal file
View File

@ -0,0 +1,41 @@
// ws2812_lib.h
#ifndef __WS2812_I2S_H__
#define __WS2812_I2S_H__
#include <stdint.h>
#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