From 8432e8c8beacd5580e19148001c0e383f92b2ac7 Mon Sep 17 00:00:00 2001 From: Markus Gritsch Date: Tue, 3 Mar 2015 10:20:02 +0100 Subject: [PATCH] Changed the ws2812 byte order from GRB to RGB There seems to be interest in using the more intuitive RGB byte order to specify the LED color. Also fixed the documentation. --- README.md | 96 +++++++++++++++++++-------------------- app/include/user_config.h | 2 +- app/modules/modules.h | 14 +++--- app/modules/ws2812.c | 56 +++++++++++++---------- 4 files changed, 87 insertions(+), 81 deletions(-) diff --git a/README.md b/README.md index d4f88930..8d66eae6 100644 --- a/README.md +++ b/README.md @@ -156,7 +156,7 @@ baudrate:9600 ``` ####Manipulate hardware like a arduino - + ```lua pin = 1 gpio.mode(pin,gpio.OUTPUT) @@ -165,10 +165,10 @@ baudrate:9600 ``` ####Write network application in nodejs style - + ```lua -- A simple http client - conn=net.createConnection(net.TCP, 0) + conn=net.createConnection(net.TCP, 0) conn:on("receive", function(conn, payload) print(payload) end ) conn:connect(80,"115.239.210.27") conn:send("GET / HTTP/1.1\r\nHost: www.baidu.com\r\n" @@ -176,15 +176,15 @@ baudrate:9600 ``` ####Or a simple http server - + ```lua -- A simple http server - srv=net.createServer(net.TCP) - srv:listen(80,function(conn) - conn:on("receive",function(conn,payload) - print(payload) + srv=net.createServer(net.TCP) + srv:listen(80,function(conn) + conn:on("receive",function(conn,payload) + print(payload) conn:send("

Hello, NodeMcu.

") - end) + end) conn:on("sent",function(conn) conn:close() end) end) ``` @@ -196,7 +196,7 @@ baudrate:9600 m = mqtt.Client("clientid", 120, "user", "password") -- setup Last Will and Testament (optional) --- Broker will publish a message with qos = 0, retain = 0, data = "offline" +-- Broker will publish a message with qos = 0, retain = 0, data = "offline" -- to topic "/lwt" if client don't send keepalive packet m:lwt("/lwt", "offline", 0, 0) @@ -204,8 +204,8 @@ m:on("connect", function(con) print ("connected") end) m:on("offline", function(con) print ("offline") end) -- on publish message receive event -m:on("message", function(conn, topic, data) - print(topic .. ":" ) +m:on("message", function(conn, topic, data) + print(topic .. ":" ) if data ~= nil then print(data) end @@ -229,29 +229,29 @@ m:close(); #### UDP client and server ```lua -- a udp server -s=net.createServer(net.UDP) +s=net.createServer(net.UDP) s:on("receive",function(s,c) print(c) end) s:listen(5683) -- a udp client -cu=net.createConnection(net.UDP) -cu:on("receive",function(cu,c) print(c) end) -cu:connect(5683,"192.168.18.101") +cu=net.createConnection(net.UDP) +cu:on("receive",function(cu,c) print(c) end) +cu:connect(5683,"192.168.18.101") cu:send("hello") ``` ####Do something shining ```lua - function led(r,g,b) - pwm.setduty(1,r) - pwm.setduty(2,g) - pwm.setduty(3,b) + function led(r,g,b) + pwm.setduty(1,r) + pwm.setduty(2,g) + pwm.setduty(3,b) end - pwm.setup(1,500,512) - pwm.setup(2,500,512) + pwm.setup(1,500,512) + pwm.setup(2,500,512) pwm.setup(3,500,512) - pwm.start(1) - pwm.start(2) + pwm.start(1) + pwm.start(2) pwm.start(3) led(512,0,0) -- red led(0,0,512) -- blue @@ -261,13 +261,13 @@ cu:send("hello") ```lua lighton=0 tmr.alarm(1,1000,1,function() - if lighton==0 then - lighton=1 - led(512,512,512) - else - lighton=0 - led(0,0,0) - end + if lighton==0 then + lighton=1 + led(512,512,512) + else + lighton=0 + led(0,0,0) + end end) ``` @@ -283,20 +283,20 @@ cu:send("hello") ####With below code, you can telnet to your esp8266 now ```lua -- a simple telnet server - s=net.createServer(net.TCP,180) - s:listen(2323,function(c) - function s_output(str) - if(c~=nil) - then c:send(str) - end - end + s=net.createServer(net.TCP,180) + s:listen(2323,function(c) + function s_output(str) + if(c~=nil) + then c:send(str) + end + end node.output(s_output, 0) -- re-direct output to function s_ouput. - c:on("receive",function(c,l) + c:on("receive",function(c,l) node.input(l) -- works like pcall(loadstring(l)) but support multiple separate line - end) - c:on("disconnection",function(c) + end) + c:on("disconnection",function(c) node.output(nil) -- un-regist the redirect output function, output goes to serial - end) + end) print("Welcome to NodeMcu world.") end) ``` @@ -325,15 +325,15 @@ cu:send("hello") -- Don't forget to release it after use t = nil ds18b20 = nil - package.loaded["ds18b20"]=nil + package.loaded["ds18b20"]=nil ``` ####Control a WS2812 based light strip ```lua - -- set the color of one LED on GPIO 2 to red - ws2812.write(4, string.char(0, 255, 0)) - -- set the color of 10 LEDs on GPIO 0 to blue - ws2812.write(3, string.char(0, 0, 255):rep(10)) + -- set the color of one LED on GPIO2 to red + ws2812.writergb(4, string.char(255, 0, 0)) + -- set the color of 10 LEDs on GPIO0 to blue + ws2812.writergb(3, string.char(0, 0, 255):rep(10)) -- first LED green, second LED white - ws2812.write(4, string.char(255, 0, 0, 255, 255, 255)) + ws2812.writergb(4, string.char(0, 255, 0, 255, 255, 255)) ``` diff --git a/app/include/user_config.h b/app/include/user_config.h index c6ec1e0e..cf207dc3 100644 --- a/app/include/user_config.h +++ b/app/include/user_config.h @@ -68,7 +68,7 @@ #define LUA_USE_MODULES_OW #define LUA_USE_MODULES_BIT #define LUA_USE_MODULES_MQTT -// #define LUA_USE_MODULES_WS2812 // TODO: put this device specific module to device driver section. +#define LUA_USE_MODULES_WS2812 // TODO: put this device specific module to device driver section. #endif /* LUA_USE_MODULES */ // TODO: put device specific module to device driver section. diff --git a/app/modules/modules.h b/app/modules/modules.h index aaa98053..619bca89 100644 --- a/app/modules/modules.h +++ b/app/modules/modules.h @@ -120,17 +120,17 @@ #if defined(LUA_USE_MODULES_WS2812) #define MODULES_WS2812 "ws2812" #define ROM_MODULES_WS2812 \ - _ROM(MODULES_WS2812, luaopen_ws2812, ws2812_map) + _ROM(MODULES_WS2812, luaopen_ws2812, ws2812_map) #else #define ROM_MODULES_WS2812 #endif -#define LUA_MODULES_ROM \ +#define LUA_MODULES_ROM \ ROM_MODULES_GPIO \ - ROM_MODULES_PWM \ - ROM_MODULES_WIFI \ - ROM_MODULES_MQTT \ + ROM_MODULES_PWM \ + ROM_MODULES_WIFI \ + ROM_MODULES_MQTT \ ROM_MODULES_I2C \ ROM_MODULES_SPI \ ROM_MODULES_TMR \ @@ -140,8 +140,8 @@ ROM_MODULES_ADC \ ROM_MODULES_UART \ ROM_MODULES_OW \ - ROM_MODULES_BIT \ - ROM_MODULES_WS2812 + ROM_MODULES_BIT \ + ROM_MODULES_WS2812 #endif diff --git a/app/modules/ws2812.c b/app/modules/ws2812.c index aab28e92..b9419181 100644 --- a/app/modules/ws2812.c +++ b/app/modules/ws2812.c @@ -8,47 +8,56 @@ * from user Markus Gritsch. * I just put this code into its own module and pushed into a forked repo, * to easily create a pull request. Thanks to Markus Gritsch for the code. - * */ // ---------------------------------------------------------------------------- -// -- This WS2812 code must be compiled with -O2 to get the timing right. +// -- This WS2812 code must be compiled with -O2 to get the timing right. Read this: // -- http://wp.josh.com/2014/05/13/ws2812-neopixels-are-not-so-finicky-once-you-get-to-know-them/ -// The ICACHE_FLASH_ATTR is there to trick the compiler and get the very first pulse width correct. +// -- The ICACHE_FLASH_ATTR is there to trick the compiler and get the very first pulse width correct. static void ICACHE_FLASH_ATTR send_ws_0(uint8_t gpio) { uint8_t i; - i = 4; - while (i--) - GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, 1 << gpio); - i = 9; - while (i--) - GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, 1 << gpio); + i = 4; while (i--) GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, 1 << gpio); + i = 9; while (i--) GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, 1 << gpio); } static void ICACHE_FLASH_ATTR send_ws_1(uint8_t gpio) { uint8_t i; - i = 8; - while (i--) - GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, 1 << gpio); - i = 6; - while (i--) - GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, 1 << gpio); + i = 8; while (i--) GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, 1 << gpio); + i = 6; while (i--) GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, 1 << gpio); } // Lua: ws2812.write(pin, "string") -// Byte triples in the string are interpreted as G R B values. -// ws2812.write(4, string.char(0, 255, 0)) uses GPIO2 and sets the first LED red. +// Byte triples in the string are interpreted as R G B values and sent to the hardware as G R B. +// ws2812.write(4, string.char(255, 0, 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_write(lua_State* L) { +// ws2812.write(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); size_t length; - const char *buffer = luaL_checklstring(L, 2, &length); + char *buffer = (char *)luaL_checklstring(L, 2, &length); // Cast away the constness. + // Initialize the output pin: platform_gpio_mode(pin, PLATFORM_GPIO_OUTPUT, PLATFORM_GPIO_FLOAT); platform_gpio_write(pin, 0); - os_delay_us(10); + // 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; + } + + // Do not remove these: + os_delay_us(1); + os_delay_us(1); + + // Send the buffer: os_intr_lock(); const char * const end = buffer + length; while (buffer != end) { @@ -68,7 +77,7 @@ static int ICACHE_FLASH_ATTR ws2812_write(lua_State* L) { #include "lrodefs.h" const LUA_REG_TYPE ws2812_map[] = { - { LSTRKEY( "write" ), LFUNCVAL( ws2812_write )}, + { LSTRKEY( "writergb" ), LFUNCVAL( ws2812_writergb )}, { LNILKEY, LNILVAL} }; @@ -77,6 +86,3 @@ LUALIB_API int luaopen_ws2812(lua_State *L) { LREGISTER(L, "ws2812", ws2812_map); return 1; } - -// ---------------------------------------------------------------------------- -