Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
Nodemcu Firmware
Commits
16953690
Commit
16953690
authored
Feb 17, 2016
by
Terry Ellison
Browse files
Merge pull request #902 from Alkorin/ws2812-buffer-1.5
ws2812 strip data buffer
parents
4501f655
47b44229
Changes
1
Hide whitespace changes
Inline
Side-by-side
app/modules/ws2812.c
View file @
16953690
...
@@ -6,6 +6,14 @@
...
@@ -6,6 +6,14 @@
#include "user_interface.h"
#include "user_interface.h"
#include "driver/uart.h"
#include "driver/uart.h"
#define CANARY_VALUE 0x32383132
typedef
struct
{
int
canary
;
int
size
;
uint8_t
values
[
0
];
}
ws2812_buffer
;
// Stream data using UART1 routed to GPIO2
// Stream data using UART1 routed to GPIO2
// NODE_DEBUG should not be activated because it also uses UART1
// 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
)
{
static
void
ICACHE_RAM_ATTR
ws2812_write
(
uint8_t
pin
,
uint8_t
*
pixels
,
uint32_t
length
)
{
...
@@ -47,13 +55,8 @@ static void ICACHE_RAM_ATTR ws2812_write(uint8_t pin, uint8_t *pixels, uint32_t
...
@@ -47,13 +55,8 @@ static void ICACHE_RAM_ATTR ws2812_write(uint8_t pin, uint8_t *pixels, uint32_t
}
}
// Lua: ws2812.writergb(pin, "string")
// Lua: ws2812.writergb(pin, "string")
// Byte triples in the string are interpreted as R G B values and sent to the hardware as G R B.
// Byte triples in the string or buffer are interpreted as R G B values and sent to the hardware as G R B.
// WARNING: this function scrambles the input buffer :
//
// a = string.char(255,0,128)
// ws212.writergb(3,a)
// =a.byte()
// (0,255,128)
// ws2812.writergb(4, string.char(255, 0, 0)) uses GPIO2 and sets the first LED red.
// 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(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.
// ws2812.writergb(4, string.char(0, 255, 0, 255, 255, 255)) first LED green, second LED white.
...
@@ -61,7 +64,19 @@ static int ICACHE_FLASH_ATTR ws2812_writergb(lua_State* L)
...
@@ -61,7 +64,19 @@ static int ICACHE_FLASH_ATTR ws2812_writergb(lua_State* L)
{
{
const
uint8_t
pin
=
luaL_checkinteger
(
L
,
1
);
const
uint8_t
pin
=
luaL_checkinteger
(
L
,
1
);
size_t
length
;
size_t
length
;
const
char
*
rgb
=
luaL_checklstring
(
L
,
2
,
&
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
// dont modify lua-internal lstring - make a copy instead
char
*
buffer
=
(
char
*
)
c_malloc
(
length
);
char
*
buffer
=
(
char
*
)
c_malloc
(
length
);
...
@@ -88,8 +103,8 @@ static int ICACHE_FLASH_ATTR ws2812_writergb(lua_State* L)
...
@@ -88,8 +103,8 @@ static int ICACHE_FLASH_ATTR ws2812_writergb(lua_State* L)
}
}
// Lua: ws2812.write(pin, "string")
// Lua: ws2812.write(pin, "string")
//
Byte triples in the string are interpreted as G R B values.
//
Lua: ws2812.write(pin, ws2812.buffer)
//
This function does not corrupt your 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(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(3, string.char(0, 0, 255):rep(10)) uses GPIO0 and sets ten LEDs blue.
...
@@ -97,23 +112,198 @@ static int ICACHE_FLASH_ATTR ws2812_writergb(lua_State* L)
...
@@ -97,23 +112,198 @@ static int ICACHE_FLASH_ATTR ws2812_writergb(lua_State* L)
static
int
ICACHE_FLASH_ATTR
ws2812_writegrb
(
lua_State
*
L
)
{
static
int
ICACHE_FLASH_ATTR
ws2812_writegrb
(
lua_State
*
L
)
{
const
uint8_t
pin
=
luaL_checkinteger
(
L
,
1
);
const
uint8_t
pin
=
luaL_checkinteger
(
L
,
1
);
size_t
length
;
size_t
length
;
const
char
*
buffer
=
luaL_checklstring
(
L
,
2
,
&
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
// Send the buffer
ws2812_write
(
pin_num
[
pin
],
(
uint8_t
*
)
buffer
,
length
);
ws2812_write
(
pin_num
[
pin
],
(
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
)
{
const
int
leds
=
luaL_checkint
(
L
,
1
);
luaL_argcheck
(
L
,
leds
>
0
,
1
,
"should be a positive integer"
);
// Allocate memory
size_t
size
=
sizeof
(
ws2812_buffer
)
+
3
*
leds
*
sizeof
(
uint8_t
);
ws2812_buffer
*
buffer
=
(
ws2812_buffer
*
)
lua_newuserdata
(
L
,
size
);
// Associate its metatable
luaL_getmetatable
(
L
,
"ws2812.buffer"
);
lua_setmetatable
(
L
,
-
2
);
// Save led strip size
buffer
->
size
=
leds
;
// Store canary for future type checks
buffer
->
canary
=
CANARY_VALUE
;
return
1
;
}
static
int
ICACHE_FLASH_ATTR
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
);
uint8_t
*
p
=
&
buffer
->
values
[
0
];
int
i
;
for
(
i
=
0
;
i
<
buffer
->
size
;
i
++
)
{
*
p
++
=
g
;
*
p
++
=
r
;
*
p
++
=
b
;
}
return
0
;
}
static
int
ICACHE_FLASH_ATTR
ws2812_buffer_fade
(
lua_State
*
L
)
{
ws2812_buffer
*
buffer
=
(
ws2812_buffer
*
)
lua_touserdata
(
L
,
1
);
const
int
fade
=
luaL_checkinteger
(
L
,
2
);
luaL_argcheck
(
L
,
buffer
&&
buffer
->
canary
==
CANARY_VALUE
,
1
,
"ws2812.buffer expected"
);
luaL_argcheck
(
L
,
fade
>
0
,
2
,
"fade value should be a strict positive number"
);
uint8_t
*
p
=
&
buffer
->
values
[
0
];
int
i
;
for
(
i
=
0
;
i
<
buffer
->
size
;
i
++
)
{
*
p
++
/=
fade
;
*
p
++
/=
fade
;
*
p
++
/=
fade
;
}
return
0
;
return
0
;
}
}
static
int
ICACHE_FLASH_ATTR
ws2812_buffer_get
(
lua_State
*
L
)
{
ws2812_buffer
*
buffer
=
(
ws2812_buffer
*
)
lua_touserdata
(
L
,
1
);
const
int
led
=
luaL_checkinteger
(
L
,
2
);
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
]);
return
3
;
}
static
int
ICACHE_FLASH_ATTR
ws2812_buffer_set
(
lua_State
*
L
)
{
ws2812_buffer
*
buffer
=
(
ws2812_buffer
*
)
lua_touserdata
(
L
,
1
);
const
int
led
=
luaL_checkinteger
(
L
,
2
);
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"
);
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
);
// 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
);
// Clean up the stack
lua_pop
(
L
,
3
);
}
else
if
(
type
==
LUA_TSTRING
)
{
size_t
len
;
const
char
*
buf
=
lua_tolstring
(
L
,
3
,
&
len
);
// Overflow check
if
(
3
*
led
+
len
>
3
*
buffer
->
size
)
{
return
luaL_error
(
L
,
"string size will exceed strip length"
);
}
c_memcpy
(
&
buffer
->
values
[
3
*
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
);
}
return
0
;
}
static
int
ICACHE_FLASH_ATTR
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"
);
lua_pushnumber
(
L
,
buffer
->
size
);
return
1
;
}
static
int
ICACHE_FLASH_ATTR
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
();
return
0
;
}
static
const
LUA_REG_TYPE
ws2812_buffer_map
[]
=
{
{
LSTRKEY
(
"fade"
),
LFUNCVAL
(
ws2812_buffer_fade
)},
{
LSTRKEY
(
"fill"
),
LFUNCVAL
(
ws2812_buffer_fill
)},
{
LSTRKEY
(
"get"
),
LFUNCVAL
(
ws2812_buffer_get
)},
{
LSTRKEY
(
"set"
),
LFUNCVAL
(
ws2812_buffer_set
)},
{
LSTRKEY
(
"size"
),
LFUNCVAL
(
ws2812_buffer_size
)},
{
LSTRKEY
(
"write"
),
LFUNCVAL
(
ws2812_buffer_write
)},
{
LSTRKEY
(
"__index"
),
LROVAL
(
ws2812_buffer_map
)},
{
LNILKEY
,
LNILVAL
}
};
static
const
LUA_REG_TYPE
ws2812_map
[]
=
static
const
LUA_REG_TYPE
ws2812_map
[]
=
{
{
{
LSTRKEY
(
"writergb"
),
LFUNCVAL
(
ws2812_writergb
)},
{
LSTRKEY
(
"writergb"
),
LFUNCVAL
(
ws2812_writergb
)},
{
LSTRKEY
(
"write"
),
LFUNCVAL
(
ws2812_writegrb
)},
{
LSTRKEY
(
"write"
),
LFUNCVAL
(
ws2812_writegrb
)},
{
LSTRKEY
(
"newBuffer"
),
LFUNCVAL
(
ws2812_new_buffer
)},
{
LNILKEY
,
LNILVAL
}
{
LNILKEY
,
LNILVAL
}
};
};
int
luaopen_ws2812
(
lua_State
*
L
)
{
int
luaopen_ws2812
(
lua_State
*
L
)
{
// TODO: Make sure that the GPIO system is initialized
// TODO: Make sure that the GPIO system is initialized
luaL_rometatable
(
L
,
"ws2812.buffer"
,
(
void
*
)
ws2812_buffer_map
);
// create metatable for ws2812.buffer
return
0
;
return
0
;
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment