Finalize work on ws2812 module
* Fix bug on first write Pin is 'HIGH' at reset, so we need to pull it down and generate a reset. * Move init code to flash section, not needed to be in iram. * Remove pin choice in API * Remove lock in ws2812_buffer_write * Remove naked malloc * Drop ws2812_writergb * Drop support of ws2812.buffers to ws2812_writegrb should use ws2812.buffers:write * Add support for <>3 colors per leds strips (RGBW) * Remove ICACHE_FLASH_ATTR * Add static const on _uartData to avoid initialization penalty
This commit is contained in:
parent
216c69f18b
commit
0577c8af0f
|
@ -1,5 +1,6 @@
|
|||
#include "module.h"
|
||||
#include "lauxlib.h"
|
||||
#include "lmem.h"
|
||||
#include "platform.h"
|
||||
#include "c_stdlib.h"
|
||||
#include "c_string.h"
|
||||
|
@ -11,33 +12,51 @@
|
|||
typedef struct {
|
||||
int canary;
|
||||
int size;
|
||||
uint8_t colorsPerLed;
|
||||
uint8_t values[0];
|
||||
} ws2812_buffer;
|
||||
|
||||
// Stream data using UART1 routed to GPIO2
|
||||
// NODE_DEBUG should not be activated because it also uses UART1
|
||||
static void ICACHE_RAM_ATTR ws2812_write(uint8_t pin, uint8_t *pixels, uint32_t length) {
|
||||
|
||||
// Data are sent LSB first, with a start bit at 0, an end bit at 1 and all inverted
|
||||
// 0b00110111 => 110111 => [0]111011[1] => 10001000 => 00
|
||||
// 0b00000111 => 000111 => [0]111000[1] => 10001110 => 01
|
||||
// 0b00110100 => 110100 => [0]001011[1] => 11101000 => 10
|
||||
// 0b00000100 => 000100 => [0]001000[1] => 11101110 => 11
|
||||
uint8_t _uartData[4] = { 0b00110111, 0b00000111, 0b00110100, 0b00000100 };
|
||||
|
||||
// Init UART1 to be able to stream WS2812 data
|
||||
// We use GPIO2 as output pin
|
||||
static void ws2812_init() {
|
||||
// Configure UART1
|
||||
// Set baudrate of UART1 to 3200000
|
||||
WRITE_PERI_REG(UART_CLKDIV(1), UART_CLK_FREQ / 3200000);
|
||||
// Set UART Configuration No parity / 6 DataBits / 1 StopBits / Invert TX
|
||||
WRITE_PERI_REG(UART_CONF0(1), UART_TXD_INV | (1 << UART_STOP_BIT_NUM_S) | (1 << UART_BIT_NUM_S));
|
||||
|
||||
// Pull GPIO2 down
|
||||
platform_gpio_mode(4, PLATFORM_GPIO_OUTPUT, PLATFORM_GPIO_FLOAT);
|
||||
platform_gpio_write(4, 0);
|
||||
|
||||
// Waits 10us to simulate a reset
|
||||
os_delay_us(10);
|
||||
|
||||
// Redirect UART1 to GPIO2
|
||||
// Disable GPIO2
|
||||
GPIO_REG_WRITE(GPIO_ENABLE_W1TC_ADDRESS, BIT2);
|
||||
// Enable Function 2 for GPIO2 (U1TXD)
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_U1TXD_BK);
|
||||
}
|
||||
|
||||
|
||||
// Stream data using UART1 routed to GPIO2
|
||||
// ws2812.init() should be called first
|
||||
//
|
||||
// NODE_DEBUG should not be activated because it also uses UART1
|
||||
static void ICACHE_RAM_ATTR ws2812_write(uint8_t *pixels, uint32_t length) {
|
||||
|
||||
// Data are sent LSB first, with a start bit at 0, an end bit at 1 and all inverted
|
||||
// 0b00110111 => 110111 => [0]111011[1] => 10001000 => 00
|
||||
// 0b00000111 => 000111 => [0]111000[1] => 10001110 => 01
|
||||
// 0b00110100 => 110100 => [0]001011[1] => 11101000 => 10
|
||||
// 0b00000100 => 000100 => [0]001000[1] => 11101110 => 11
|
||||
// Array declared as static const to avoid runtime generation
|
||||
// But declared in ".data" section to avoid read penalty from FLASH
|
||||
static const __attribute__((section(".data._uartData"))) uint8_t _uartData[4] = { 0b00110111, 0b00000111, 0b00110100, 0b00000100 };
|
||||
|
||||
uint8_t *end = pixels + length;
|
||||
|
||||
do {
|
||||
uint8_t value = *pixels++;
|
||||
|
||||
|
@ -52,94 +71,37 @@ static void ICACHE_RAM_ATTR ws2812_write(uint8_t pin, uint8_t *pixels, uint32_t
|
|||
WRITE_PERI_REG(UART_FIFO(1), _uartData[(value >> 0) & 3]);
|
||||
|
||||
} while(pixels < end);
|
||||
|
||||
}
|
||||
|
||||
// Lua: ws2812.writergb(pin, "string")
|
||||
// Byte triples in the string or buffer are interpreted as R G B values and sent to the hardware as G R B.
|
||||
// Lua: ws2812.write("string")
|
||||
// Byte triples in the string are interpreted as G R B values.
|
||||
//
|
||||
// ws2812.writergb(4, string.char(255, 0, 0)) uses GPIO2 and sets the first LED red.
|
||||
// ws2812.writergb(3, string.char(0, 0, 255):rep(10)) uses GPIO0 and sets ten LEDs blue.
|
||||
// ws2812.writergb(4, string.char(0, 255, 0, 255, 255, 255)) first LED green, second LED white.
|
||||
static int ICACHE_FLASH_ATTR ws2812_writergb(lua_State* L)
|
||||
{
|
||||
const uint8_t pin = luaL_checkinteger(L, 1);
|
||||
// ws2812.init() should be called first
|
||||
//
|
||||
// ws2812.write(string.char(0, 255, 0)) sets the first LED red.
|
||||
// ws2812.write(string.char(0, 0, 255):rep(10)) sets ten LEDs blue.
|
||||
// ws2812.write(string.char(255, 0, 0, 255, 255, 255)) first LED green, second LED white.
|
||||
static int ws2812_writegrb(lua_State* L) {
|
||||
size_t length;
|
||||
const char *rgb;
|
||||
|
||||
// Buffer or string
|
||||
if(lua_isuserdata(L, 2)) {
|
||||
ws2812_buffer * buffer = (ws2812_buffer*)lua_touserdata(L, 2);
|
||||
|
||||
luaL_argcheck(L, buffer && buffer->canary == CANARY_VALUE, 2, "ws2812.buffer expected");
|
||||
|
||||
rgb = &buffer->values[0];
|
||||
length = 3*buffer->size;
|
||||
} else {
|
||||
rgb = luaL_checklstring(L, 2, &length);
|
||||
}
|
||||
|
||||
// dont modify lua-internal lstring - make a copy instead
|
||||
char *buffer = (char *)c_malloc(length);
|
||||
c_memcpy(buffer, rgb, length);
|
||||
|
||||
// Ignore incomplete Byte triples at the end of buffer:
|
||||
length -= length % 3;
|
||||
|
||||
// Rearrange R G B values to G R B order needed by WS2812 LEDs:
|
||||
size_t i;
|
||||
for (i = 0; i < length; i += 3) {
|
||||
const char r = buffer[i];
|
||||
const char g = buffer[i + 1];
|
||||
buffer[i] = g;
|
||||
buffer[i + 1] = r;
|
||||
}
|
||||
const char *values = luaL_checklstring(L, 1, &length);
|
||||
|
||||
// Send the buffer
|
||||
ws2812_write(pin_num[pin], (uint8_t*) buffer, length);
|
||||
|
||||
c_free(buffer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Lua: ws2812.write(pin, "string")
|
||||
// Lua: ws2812.write(pin, ws2812.buffer)
|
||||
// Byte triples in the string or buffer are interpreted as G R B values.
|
||||
//
|
||||
// ws2812.write(4, string.char(0, 255, 0)) uses GPIO2 and sets the first LED red.
|
||||
// ws2812.write(3, string.char(0, 0, 255):rep(10)) uses GPIO0 and sets ten LEDs blue.
|
||||
// ws2812.write(4, string.char(255, 0, 0, 255, 255, 255)) first LED green, second LED white.
|
||||
static int ICACHE_FLASH_ATTR ws2812_writegrb(lua_State* L) {
|
||||
const uint8_t pin = luaL_checkinteger(L, 1);
|
||||
size_t length;
|
||||
const char *values;
|
||||
|
||||
// Buffer or string
|
||||
if(lua_isuserdata(L, 2)) {
|
||||
ws2812_buffer * buffer = (ws2812_buffer*)lua_touserdata(L, 2);
|
||||
|
||||
luaL_argcheck(L, buffer && buffer->canary == CANARY_VALUE, 2, "ws2812.buffer expected");
|
||||
|
||||
values = &buffer->values[0];
|
||||
length = 3*buffer->size;
|
||||
} else {
|
||||
values = luaL_checklstring(L, 2, &length);
|
||||
}
|
||||
|
||||
// Send the buffer
|
||||
ws2812_write(pin_num[pin], (uint8_t*) values, length);
|
||||
ws2812_write((uint8_t*) values, length);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Handle a buffer where we can store led values
|
||||
static int ICACHE_FLASH_ATTR ws2812_new_buffer(lua_State *L) {
|
||||
static int ws2812_new_buffer(lua_State *L) {
|
||||
const int leds = luaL_checkint(L, 1);
|
||||
const int colorsPerLed = luaL_checkint(L, 2);
|
||||
|
||||
luaL_argcheck(L, leds > 0, 1, "should be a positive integer");
|
||||
luaL_argcheck(L, colorsPerLed > 0, 2, "should be a positive integer");
|
||||
|
||||
// Allocate memory
|
||||
size_t size = sizeof(ws2812_buffer) + 3*leds*sizeof(uint8_t);
|
||||
size_t size = sizeof(ws2812_buffer) + colorsPerLed*leds*sizeof(uint8_t);
|
||||
ws2812_buffer * buffer = (ws2812_buffer*)lua_newuserdata(L, size);
|
||||
|
||||
// Associate its metatable
|
||||
|
@ -148,6 +110,7 @@ static int ICACHE_FLASH_ATTR ws2812_new_buffer(lua_State *L) {
|
|||
|
||||
// Save led strip size
|
||||
buffer->size = leds;
|
||||
buffer->colorsPerLed = colorsPerLed;
|
||||
|
||||
// Store canary for future type checks
|
||||
buffer->canary = CANARY_VALUE;
|
||||
|
@ -155,27 +118,37 @@ static int ICACHE_FLASH_ATTR ws2812_new_buffer(lua_State *L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int ICACHE_FLASH_ATTR ws2812_buffer_fill(lua_State* L) {
|
||||
static int ws2812_buffer_fill(lua_State* L) {
|
||||
ws2812_buffer * buffer = (ws2812_buffer*)lua_touserdata(L, 1);
|
||||
|
||||
luaL_argcheck(L, buffer && buffer->canary == CANARY_VALUE, 1, "ws2812.buffer expected");
|
||||
|
||||
const int g = luaL_checkinteger(L, 2);
|
||||
const int r = luaL_checkinteger(L, 3);
|
||||
const int b = luaL_checkinteger(L, 4);
|
||||
// Grab colors
|
||||
int i, j;
|
||||
int * colors = luaM_malloc(L, buffer->colorsPerLed * sizeof(int));
|
||||
|
||||
uint8_t * p = &buffer->values[0];
|
||||
int i;
|
||||
for(i = 0; i < buffer->size; i++) {
|
||||
*p++ = g;
|
||||
*p++ = r;
|
||||
*p++ = b;
|
||||
for (i = 0; i < buffer->colorsPerLed; i++)
|
||||
{
|
||||
colors[i] = luaL_checkinteger(L, 2+i);
|
||||
}
|
||||
|
||||
// Fill buffer
|
||||
uint8_t * p = &buffer->values[0];
|
||||
for(i = 0; i < buffer->size; i++)
|
||||
{
|
||||
for (j = 0; j < buffer->colorsPerLed; j++)
|
||||
{
|
||||
*p++ = colors[j];
|
||||
}
|
||||
}
|
||||
|
||||
// Free memory
|
||||
luaM_free(L, colors);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ICACHE_FLASH_ATTR ws2812_buffer_fade(lua_State* L) {
|
||||
static int ws2812_buffer_fade(lua_State* L) {
|
||||
ws2812_buffer * buffer = (ws2812_buffer*)lua_touserdata(L, 1);
|
||||
const int fade = luaL_checkinteger(L, 2);
|
||||
|
||||
|
@ -184,32 +157,33 @@ static int ICACHE_FLASH_ATTR ws2812_buffer_fade(lua_State* L) {
|
|||
|
||||
uint8_t * p = &buffer->values[0];
|
||||
int i;
|
||||
for(i = 0; i < buffer->size; i++) {
|
||||
*p++ /= fade;
|
||||
*p++ /= fade;
|
||||
for(i = 0; i < buffer->size * buffer->colorsPerLed; i++)
|
||||
{
|
||||
*p++ /= fade;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ICACHE_FLASH_ATTR ws2812_buffer_get(lua_State* L) {
|
||||
static int ws2812_buffer_get(lua_State* L) {
|
||||
ws2812_buffer * buffer = (ws2812_buffer*)lua_touserdata(L, 1);
|
||||
const int led = luaL_checkinteger(L, 2);
|
||||
const int led = luaL_checkinteger(L, 2) - 1;
|
||||
|
||||
luaL_argcheck(L, buffer && buffer->canary == CANARY_VALUE, 1, "ws2812.buffer expected");
|
||||
luaL_argcheck(L, led >= 0 && led < buffer->size, 2, "index out of range");
|
||||
|
||||
lua_pushnumber(L, buffer->values[3*led+0]);
|
||||
lua_pushnumber(L, buffer->values[3*led+1]);
|
||||
lua_pushnumber(L, buffer->values[3*led+2]);
|
||||
int i;
|
||||
for (i = 0; i < buffer->colorsPerLed; i++)
|
||||
{
|
||||
lua_pushnumber(L, buffer->values[buffer->colorsPerLed*led+i]);
|
||||
}
|
||||
|
||||
return 3;
|
||||
return buffer->colorsPerLed;
|
||||
}
|
||||
|
||||
static int ICACHE_FLASH_ATTR ws2812_buffer_set(lua_State* L) {
|
||||
static int ws2812_buffer_set(lua_State* L) {
|
||||
ws2812_buffer * buffer = (ws2812_buffer*)lua_touserdata(L, 1);
|
||||
const int led = luaL_checkinteger(L, 2);
|
||||
const int led = luaL_checkinteger(L, 2) - 1;
|
||||
|
||||
luaL_argcheck(L, buffer && buffer->canary == CANARY_VALUE, 1, "ws2812.buffer expected");
|
||||
luaL_argcheck(L, led >= 0 && led < buffer->size, 2, "index out of range");
|
||||
|
@ -217,18 +191,18 @@ static int ICACHE_FLASH_ATTR ws2812_buffer_set(lua_State* L) {
|
|||
int type = lua_type(L, 3);
|
||||
if(type == LUA_TTABLE)
|
||||
{
|
||||
// Get g,r,b values and push them on stash
|
||||
lua_rawgeti(L, 3, 1);
|
||||
lua_rawgeti(L, 3, 2);
|
||||
lua_rawgeti(L, 3, 3);
|
||||
int i;
|
||||
for (i = 0; i < buffer->colorsPerLed; i++)
|
||||
{
|
||||
// Get value and push it on stack
|
||||
lua_rawgeti(L, 3, i+1);
|
||||
|
||||
// Convert them as int and store them in buffer
|
||||
buffer->values[3*led+0] = lua_tonumber(L, -3);
|
||||
buffer->values[3*led+1] = lua_tonumber(L, -2);
|
||||
buffer->values[3*led+2] = lua_tonumber(L, -1);
|
||||
// Convert it as int and store them in buffer
|
||||
buffer->values[buffer->colorsPerLed*led+i] = lua_tonumber(L, -1);
|
||||
}
|
||||
|
||||
// Clean up the stack
|
||||
lua_pop(L, 3);
|
||||
lua_pop(L, buffer->colorsPerLed);
|
||||
}
|
||||
else if(type == LUA_TSTRING)
|
||||
{
|
||||
|
@ -236,24 +210,26 @@ static int ICACHE_FLASH_ATTR ws2812_buffer_set(lua_State* L) {
|
|||
const char * buf = lua_tolstring(L, 3, &len);
|
||||
|
||||
// Overflow check
|
||||
if( 3*led + len > 3*buffer->size )
|
||||
if( buffer->colorsPerLed*led + len > buffer->colorsPerLed*buffer->size )
|
||||
{
|
||||
return luaL_error(L, "string size will exceed strip length");
|
||||
}
|
||||
|
||||
c_memcpy(&buffer->values[3*led], buf, len);
|
||||
c_memcpy(&buffer->values[buffer->colorsPerLed*led], buf, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer->values[3*led+0] = luaL_checkinteger(L, 3);
|
||||
buffer->values[3*led+1] = luaL_checkinteger(L, 4);
|
||||
buffer->values[3*led+2] = luaL_checkinteger(L, 5);
|
||||
int i;
|
||||
for (i = 0; i < buffer->colorsPerLed; i++)
|
||||
{
|
||||
buffer->values[buffer->colorsPerLed*led+i] = luaL_checkinteger(L, 3+i);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ICACHE_FLASH_ATTR ws2812_buffer_size(lua_State* L) {
|
||||
static int ws2812_buffer_size(lua_State* L) {
|
||||
ws2812_buffer * buffer = (ws2812_buffer*)lua_touserdata(L, 1);
|
||||
|
||||
luaL_argcheck(L, buffer && buffer->canary == CANARY_VALUE, 1, "ws2812.buffer expected");
|
||||
|
@ -263,20 +239,13 @@ static int ICACHE_FLASH_ATTR ws2812_buffer_size(lua_State* L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int ICACHE_FLASH_ATTR ws2812_buffer_write(lua_State* L) {
|
||||
static int ws2812_buffer_write(lua_State* L) {
|
||||
ws2812_buffer * buffer = (ws2812_buffer*)lua_touserdata(L, 1);
|
||||
const uint8_t pin = luaL_checkinteger(L, 2);
|
||||
|
||||
luaL_argcheck(L, buffer && buffer->canary == CANARY_VALUE, 1, "ws2812.buffer expected");
|
||||
|
||||
// Initialize the output pin
|
||||
platform_gpio_mode(pin, PLATFORM_GPIO_OUTPUT, PLATFORM_GPIO_FLOAT);
|
||||
platform_gpio_write(pin, 0);
|
||||
|
||||
// Send the buffer
|
||||
ets_intr_lock();
|
||||
ws2812_write(pin_num[pin], &buffer->values[0], 3*buffer->size);
|
||||
ets_intr_unlock();
|
||||
ws2812_write(buffer->values, buffer->colorsPerLed*buffer->size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -295,9 +264,9 @@ static const LUA_REG_TYPE ws2812_buffer_map[] =
|
|||
|
||||
static const LUA_REG_TYPE ws2812_map[] =
|
||||
{
|
||||
{ LSTRKEY( "writergb" ), LFUNCVAL( ws2812_writergb )},
|
||||
{ LSTRKEY( "write" ), LFUNCVAL( ws2812_writegrb )},
|
||||
{ LSTRKEY( "newBuffer" ), LFUNCVAL( ws2812_new_buffer )},
|
||||
{ LSTRKEY( "init" ), LFUNCVAL( ws2812_init )},
|
||||
{ LNILKEY, LNILVAL}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,57 +1,164 @@
|
|||
# WS2812 Module
|
||||
| Since | Origin / Contributor | Maintainer | Source |
|
||||
| :----- | :-------------------- | :---------- | :------ |
|
||||
| 2015-02-05 | [Till Klocke](https://github.com/dereulenspiegel) | [Till Klocke](https://github.com/dereulenspiegel) | [ws2812.c](../../../app/modules/ws2812.c)|
|
||||
| 2015-02-05 | [Till Klocke](https://github.com/dereulenspiegel), [Thomas Soëte](https://github.com/Alkorin) | [Till Klocke](https://github.com/dereulenspiegel) | [ws2812.c](../../../app/modules/ws2812.c)|
|
||||
|
||||
ws2812 is a library to handle ws2812-like led strips.
|
||||
It works at least on WS2812, WS2812b, APA104, SK6812 (RGB or RGBW).
|
||||
|
||||
## ws2812.write()
|
||||
Send GRB data in 8 bits to a WS2812 chain.
|
||||
The library uses UART1 routed on GPIO2 (Pin D4 on NodeMCU DEVKIT) to
|
||||
generate the bitstream.
|
||||
|
||||
#### Syntax
|
||||
`ws2812.writegrb(pin, string)`
|
||||
## ws2812.init()
|
||||
Initialize UART1 and GPIO2, should be called once and before write()
|
||||
|
||||
#### Parameters
|
||||
- `pin` is ignored. Only works with GPIO2.
|
||||
- `string` payload to be sent to one or more WS2812 LEDs.
|
||||
It should be composed from a GRB triplet per element.
|
||||
- `G1` the first pixel's Green channel (0-255)
|
||||
- `R1` the first pixel's Red channel (0-255)
|
||||
- `B1` the first pixel's Blue channel (0-255)<br />
|
||||
... You can connect a lot of WS2812 ...
|
||||
- `G2`, `R2`, `B2` are the next WS2812's Green, Red, and Blue channel parameters
|
||||
none
|
||||
|
||||
#### Returns
|
||||
`nil`
|
||||
|
||||
```lua
|
||||
g = 0
|
||||
r = 255
|
||||
b = 0
|
||||
leds_grb = string.char(g,r,b, g,r,b)
|
||||
ws2812.write(2, leds_grb) -- turn two WS2812Bs to red, connected to pin GPIO2
|
||||
```
|
||||
|
||||
## ws2812.writergb()
|
||||
Send GRB data in 8bits to a WS2812 chain.
|
||||
## ws2812.write()
|
||||
Send data to a led strip using its native format which is generally Green,Red,Blue for RGB strips
|
||||
and Green,Red,Blue,White for RGBW strips.
|
||||
|
||||
#### Syntax
|
||||
`ws2812.writergb(pin, string)`
|
||||
`ws2812.write(string)`
|
||||
|
||||
#### Parameters
|
||||
- `pin` is ignored. Only works with GPIO2.
|
||||
- `string` payload to be sent to one or more WS2812 LEDs.
|
||||
It should be composed from an RGB triplet per element.
|
||||
- `R1` the first pixel's Red channel (0-255)
|
||||
- `G1` the first pixel's Green channel (0-255)
|
||||
- `B1` the first pixel's Blue channel (0-255)<br />
|
||||
... You can connect a lot of WS2812 ...
|
||||
- `R2`, `G2`, `B2` are the next WS2812's Red, Green, and Blue channel parameters
|
||||
- `string` payload to be sent to one or more WS2812 like leds.
|
||||
|
||||
#### Returns
|
||||
`nil`
|
||||
|
||||
#### Example
|
||||
```lua
|
||||
leds_rgb = string.char(255,0,0, 0,255,0, 0,0,255)
|
||||
ws2812.writergb(2, leds_rgb) -- turn three WS2812Bs to red, green, and blue respectively
|
||||
ws2812.init()
|
||||
ws2812.write(string.char(255,0,0,255,0,0) -- turn the two first RGB leds to green
|
||||
```
|
||||
|
||||
```lua
|
||||
ws2812.init()
|
||||
ws2812.write(string.char(0,0,0,255,0,0,0,255) -- turn the two first RGBW leds to white
|
||||
```
|
||||
|
||||
# Buffer module
|
||||
For more advanced animations, it is useful to keep a "framebuffer" of the strip,
|
||||
interact with it and flush it to the strip.
|
||||
|
||||
For this purpose, the ws2812 library offers a read/write buffer.
|
||||
|
||||
#### Example
|
||||
Led chaser with a RGBW strip
|
||||
```lua
|
||||
local i, b = 0, ws2812.newBuffer(300, 4); b:fill(0,0,0,0); tmr.alarm(0, 50, 1, function()
|
||||
i=i+1
|
||||
b:fade(2)
|
||||
b:set(i%b:size()+1, 0, 0, 0, 255)
|
||||
b:write()
|
||||
end)
|
||||
```
|
||||
|
||||
## ws2812.newBuffer()
|
||||
Allocate a new memory buffer to store led values.
|
||||
|
||||
#### Syntax
|
||||
`ws2812.newBuffer(numberOfLeds, bytesPerLed)`
|
||||
|
||||
#### Parameters
|
||||
- `numberOfLeds` length of the led strip
|
||||
- `bytesPerLed` 3 for RGB strips and 4 for RGBW strips
|
||||
|
||||
#### Returns
|
||||
`ws2812.buffer`
|
||||
|
||||
## ws2812.buffer:get()
|
||||
Return the value at the given position
|
||||
|
||||
#### Syntax
|
||||
`buffer:get(index)`
|
||||
|
||||
#### Parameters
|
||||
- `index` position in the buffer (1 for first led)
|
||||
|
||||
#### Returns
|
||||
`(color)`
|
||||
|
||||
#### Example
|
||||
```lua
|
||||
buffer:get(2) -- return the color of the second led
|
||||
```
|
||||
## ws2812.buffer:set()
|
||||
Set the value at the given position
|
||||
|
||||
#### Syntax
|
||||
`buffer:set(index, color)`
|
||||
|
||||
#### Parameters
|
||||
- `index` position in the buffer (1 for the first led)
|
||||
- `color` bytes of the color
|
||||
|
||||
#### Returns
|
||||
`nil`
|
||||
|
||||
#### Example
|
||||
```lua
|
||||
buffer:set(1, 255, 0, 0) -- set the first led green for a RGB strip
|
||||
```
|
||||
## ws2812.buffer:size()
|
||||
Return the size of the buffer in number of leds
|
||||
|
||||
#### Syntax
|
||||
`buffer:size()`
|
||||
|
||||
#### Parameters
|
||||
none
|
||||
|
||||
#### Returns
|
||||
`int`
|
||||
|
||||
## ws2812.buffer:fill()
|
||||
Fill the buffer with the given color.
|
||||
The number of given bytes must match the number of bytesPerLed of the buffer
|
||||
|
||||
#### Syntax
|
||||
`buffer:fill(color)`
|
||||
|
||||
#### Parameters
|
||||
- `color` bytes of the color
|
||||
|
||||
#### Returns
|
||||
`nil`
|
||||
|
||||
#### Example
|
||||
```lua
|
||||
buffer:fill(0, 0, 0) -- fill the buffer with black for a RGB strip
|
||||
```
|
||||
## ws2812.buffer:fade()
|
||||
Divide each byte of each led by the given value. Useful for a fading effect
|
||||
|
||||
#### Syntax
|
||||
`buffer:fade(value)`
|
||||
|
||||
#### Parameters
|
||||
- `value` value by which divide each byte
|
||||
|
||||
#### Returns
|
||||
`nil`
|
||||
|
||||
#### Example
|
||||
```lua
|
||||
buffer:fade(2)
|
||||
```
|
||||
## ws2812.buffer:write()
|
||||
Output the buffer to the led strip
|
||||
|
||||
#### Syntax
|
||||
`buffer:write()`
|
||||
|
||||
#### Parameters
|
||||
none
|
||||
|
||||
#### Returns
|
||||
`nil`
|
||||
|
||||
|
|
Loading…
Reference in New Issue