Skip to content

Commit

Permalink
Update rmt translator (#3629)
Browse files Browse the repository at this point in the history
* Choose the number of RMT buffers in the ws2812 module.

The number of buffers required for optimal operation should be selected
by the ws2812 module, not the caller.

* Add parameters for RGB LED bit times.

This patch adds compatibility for different RGB LEDS besides the WS2812.
ESP evaluation boards like the ESP32-C3-DevKitM-1 use an SK68XXMINI-HS
RGB LED which does not respond to the timings of this module.
The patch adds optional parameters for the bit timings to the write
function. If the new parameters are not supplied, the old values are used.
An example for the SK68XXMINI-HS is provided in the documentation.

* Remove restrictions from RTM translator.

The old RMT translator was not able to split the bits of the source
data into the size requested by the RMT transmitter. Either all 8 bits
of an input byte were translated or none.
The new routine removes the restriction by delivering exactly the
requested amount of data to the transmitter, which results in a more
balanced buffering of translated data under load.

* Add a parameter for the RGB LED reset time.

This patch introduces a new optional parameter for the reset time
in the RGB LED communication. The default is 51.2 microseconds. A
value of 0 sends no reset signal, which allows a small optimisation
for consecutive write commands.

Please note that the reset time of the old code should be 50
microseconds, as the define WS2812_DURATION_RESET suggested. Due to the
restrictions of the old RMT translator routine, it was slightly
increased to 51.2 microseconds. This patch keeps the value of 51.2
microseconds to be as compatible as possible.

* Minimize the time drift between RMT channels.

Place all RMT channels in a group to minimize the time drift between
the signals. Please note that this feature is not available on all
platforms.

* Fix the description of the SK6812 LED in the example code.

The SK6812 expects the data for the green LED first, then red and
finally blue. It should be described as a GRB LED.
  • Loading branch information
docbacardi authored Feb 7, 2024
1 parent 10e3783 commit 14cdff1
Show file tree
Hide file tree
Showing 4 changed files with 289 additions and 76 deletions.
111 changes: 110 additions & 1 deletion components/modules/ws2812.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@
#define SHIFT_LOGICAL 0
#define SHIFT_CIRCULAR 1

// The default bit H & L durations in multiples of 100ns.
#define WS2812_DURATION_T0H 4
#define WS2812_DURATION_T0L 7
#define WS2812_DURATION_T1H 8
#define WS2812_DURATION_T1L 6
// The default reset duration in multiples of 100ns.
#define WS2812_DURATION_RESET 512


typedef struct {
int size;
Expand All @@ -33,6 +41,7 @@ static void ws2812_cleanup( lua_State *L, int pop )
// ws2812.write({pin = 4, data = string.char(255, 0, 0, 255, 255, 255)}) first LED green, second LED white.
static int ws2812_write( lua_State* L )
{
int type;
int top = lua_gettop( L );

for (int stack = 1; stack <= top; stack++) {
Expand All @@ -56,6 +65,106 @@ static int ws2812_write( lua_State* L )
int gpio_num = luaL_checkint( L, -1 );
lua_pop( L, 1 );

//
// retrieve reset
// This is an optional parameter which defaults to WS2812_DURATION_RESET.
//
int reset = WS2812_DURATION_RESET;
type = lua_getfield( L, stack, "reset" );
if (type!=LUA_TNIL )
{
if (!lua_isnumber( L, -1 )) {
ws2812_cleanup( L, 1 );
return luaL_argerror( L, stack, "invalid reset" );
}
reset = luaL_checkint( L, -1 );
if ((reset<0) || (reset>0xfffe)) {
ws2812_cleanup( L, 1 );
return luaL_argerror( L, stack, "reset must be 0<=reset<=65534" );
}
}
lua_pop( L, 1 );

//
// retrieve t0h
// This is an optional parameter which defaults to WS2812_DURATION_T0H.
//
int t0h = WS2812_DURATION_T0H;
type = lua_getfield( L, stack, "t0h" );
if (type!=LUA_TNIL )
{
if (!lua_isnumber( L, -1 )) {
ws2812_cleanup( L, 1 );
return luaL_argerror( L, stack, "invalid t0h" );
}
t0h = luaL_checkint( L, -1 );
if ((t0h<1) || (t0h>0x7fff)) {
ws2812_cleanup( L, 1 );
return luaL_argerror( L, stack, "t0h must be 1<=t0h<=32767" );
}
}
lua_pop( L, 1 );

//
// retrieve t0l
// This is an optional parameter which defaults to WS2812_DURATION_T0L.
//
int t0l = WS2812_DURATION_T0L;
type = lua_getfield( L, stack, "t0l" );
if (type!=LUA_TNIL )
{
if (!lua_isnumber( L, -1 )) {
ws2812_cleanup( L, 1 );
return luaL_argerror( L, stack, "invalid t0l" );
}
t0l = luaL_checkint( L, -1 );
if ((t0l<1) || (t0l>0x7fff)) {
ws2812_cleanup( L, 1 );
return luaL_argerror( L, stack, "t0l must be 1<=t0l<=32767" );
}
}
lua_pop( L, 1 );

//
// retrieve t1h
// This is an optional parameter which defaults to WS2812_DURATION_T1H.
//
int t1h = WS2812_DURATION_T1H;
type = lua_getfield( L, stack, "t1h" );
if (type!=LUA_TNIL )
{
if (!lua_isnumber( L, -1 )) {
ws2812_cleanup( L, 1 );
return luaL_argerror( L, stack, "invalid t1h" );
}
t1h = luaL_checkint( L, -1 );
if ((t1h<1) || (t1h>0x7fff)) {
ws2812_cleanup( L, 1 );
return luaL_argerror( L, stack, "t1h must be 1<=t1h<=32767" );
}
}
lua_pop( L, 1 );

//
// retrieve t1l
// This is an optional parameter which defaults to WS2812_DURATION_T1L.
//
int t1l = WS2812_DURATION_T1L;
type = lua_getfield( L, stack, "t1l" );
if (type!=LUA_TNIL )
{
if (!lua_isnumber( L, -1 )) {
ws2812_cleanup( L, 1 );
return luaL_argerror( L, stack, "invalid t1l" );
}
t1l = luaL_checkint( L, -1 );
if ((t1l<1) || (t1l>0x7fff)) {
ws2812_cleanup( L, 1 );
return luaL_argerror( L, stack, "t1l must be 1<=t1l<=32767" );
}
}
lua_pop( L, 1 );

//
// retrieve data
//
Expand Down Expand Up @@ -83,7 +192,7 @@ static int ws2812_write( lua_State* L )
lua_pop( L, 1 );

// prepare channel
if (platform_ws2812_setup( gpio_num, 1, (const uint8_t *)data, length ) != PLATFORM_OK) {
if (platform_ws2812_setup( gpio_num, reset, t0h, t0l, t1h, t1l, (const uint8_t *)data, length ) != PLATFORM_OK) {
ws2812_cleanup( L, 0 );
return luaL_argerror( L, stack, "can't set up chain" );
}
Expand Down
2 changes: 1 addition & 1 deletion components/platform/include/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ int platform_dht_read( uint8_t gpio_num, uint8_t wakeup_ms, uint8_t *data );
// WS2812 platform interface

void platform_ws2812_init( void );
int platform_ws2812_setup( uint8_t gpio_num, uint8_t num_mem, const uint8_t *data, size_t len );
int platform_ws2812_setup( uint8_t gpio_num, uint32_t reset, uint32_t bit0h, uint32_t bit0l, uint32_t bit1h, uint32_t bit1l, const uint8_t *data, size_t len );
int platform_ws2812_release( void );
int platform_ws2812_send( void );

Expand Down
Loading

0 comments on commit 14cdff1

Please sign in to comment.