Skip to content

Commit c1c750d

Browse files
committed
Initial commit
0 parents  commit c1c750d

File tree

5 files changed

+194
-0
lines changed

5 files changed

+194
-0
lines changed

Diff for: CMakeLists.txt

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
idf_component_register(
2+
SRCS "ws2812.c"
3+
INCLUDE_DIRS include
4+
)

Diff for: LICENSE

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
This is free and unencumbered software released into the public domain.
2+
3+
Anyone is free to copy, modify, publish, use, compile, sell, or
4+
distribute this software, either in source code form or as a compiled
5+
binary, for any purpose, commercial or non-commercial, and by any
6+
means.
7+
8+
In jurisdictions that recognize copyright laws, the author or authors
9+
of this software dedicate any and all copyright interest in the
10+
software to the public domain. We make this dedication for the benefit
11+
of the public at large and to the detriment of our heirs and
12+
successors. We intend this dedication to be an overt act of
13+
relinquishment in perpetuity of all present and future rights to this
14+
software under copyright law.
15+
16+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19+
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20+
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22+
OTHER DEALINGS IN THE SOFTWARE.
23+
24+
For more information, please refer to <http://unlicense.org>

Diff for: README.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# ESP32 component: WS2812 LED driver
2+
3+
ESP32 component for controlling WS2812 or compatible ("Neopixel") addressable LEDs using the RMT peripheral of the ESP32.
4+
5+
Based on code from https://github.com/JSchaenzle/ESP32-NeoPixel-WS2812-RMT.
6+
7+
Licensed using the "Unlicense". This software can be considered public domain.

Diff for: include/ws2812.h

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#pragma once
2+
3+
#include <stdint.h>
4+
#include <esp_err.h>
5+
#include <driver/gpio.h>
6+
7+
__BEGIN_DECLS
8+
9+
/**
10+
* Initialize the WS2812 driver.
11+
* @return ESP_OK on success; any other value indicates an error
12+
*/
13+
extern esp_err_t ws2812_init(gpio_num_t aGpioPin);
14+
15+
/**
16+
* Enable power to the WS2812 bar.
17+
* @return ESP_OK on success; any other value indicates an error
18+
*/
19+
extern esp_err_t ws2812_enable(int gpio_pin);
20+
21+
/**
22+
* Disable power to the WS2812 bar.
23+
* @return ESP_OK on success; any other value indicates an error
24+
*/
25+
extern esp_err_t ws2812_disable(void);
26+
27+
/**
28+
* Send color-data to the WS2812 bus.
29+
* @param data the data-bytes to send on the bus.
30+
* @param len the data-length.
31+
* @return ESP_OK on success; any other value indicates an error
32+
*/
33+
extern esp_err_t ws2812_send_data(uint8_t *data, int len);
34+
35+
__END_DECLS

Diff for: ws2812.c

+124
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
//This driver uses the ESP32 RMT peripheral to drive "Neopixel" compatible LEDs
2+
//The usage of the RMT peripheral has been implemented using work by JSchaenzie:
3+
//you can find his work at https://github.com/JSchaenzle/ESP32-NeoPixel-WS2812-RMT
4+
5+
#include <sdkconfig.h>
6+
7+
#include <stdbool.h>
8+
#include <stdint.h>
9+
#include <stdio.h>
10+
#include <string.h>
11+
12+
#include <freertos/FreeRTOS.h>
13+
#include <freertos/task.h>
14+
#include <esp_err.h>
15+
#include <esp_log.h>
16+
17+
#include <driver/gpio.h>
18+
#include <driver/rmt.h>
19+
20+
static const char *TAG = "ws2812";
21+
22+
#define WS2812_RMT_CHANNEL RMT_CHANNEL_0
23+
24+
#define T0H 14 // 0 bit high time
25+
#define T1H 52 // 1 bit high time
26+
#define TL 52 // low time for either bit
27+
28+
static bool gActive = false;
29+
rmt_item32_t* gBuffer = NULL;
30+
int gBufferLength = 0;
31+
gpio_num_t gPin;
32+
33+
esp_err_t ws2812_init(gpio_num_t aGpioPin) {
34+
if (gActive) return ESP_OK;
35+
gpio_config_t io_conf = {
36+
.intr_type = GPIO_INTR_DISABLE,
37+
.mode = GPIO_MODE_OUTPUT,
38+
.pin_bit_mask = 1LL << aGpioPin,
39+
.pull_down_en = 0,
40+
.pull_up_en = 0,
41+
};
42+
esp_err_t res = gpio_config(&io_conf);
43+
if (res != ESP_OK) return res;
44+
rmt_config_t config;
45+
config.rmt_mode = RMT_MODE_TX;
46+
config.channel = WS2812_RMT_CHANNEL;
47+
config.gpio_num = aGpioPin;
48+
config.mem_block_num = 3;
49+
config.tx_config.loop_en = false;
50+
config.tx_config.carrier_en = false;
51+
config.tx_config.idle_output_en = true;
52+
config.tx_config.idle_level = 0;
53+
config.clk_div = 2;
54+
res = rmt_config(&config);
55+
if (res != ESP_OK) return res;
56+
res = rmt_driver_install(config.channel, 0, 0);
57+
if (res != ESP_OK) return res;
58+
gActive = true;
59+
gPin = aGpioPin;
60+
return ESP_OK;
61+
}
62+
63+
esp_err_t ws2812_deinit(void) {
64+
if (!gActive) return ESP_OK;
65+
esp_err_t res = rmt_driver_uninstall(WS2812_RMT_CHANNEL);
66+
if (res != ESP_OK) return res;
67+
gpio_config_t io_conf = {
68+
.intr_type = GPIO_INTR_DISABLE,
69+
.mode = GPIO_MODE_INPUT,
70+
.pin_bit_mask = 1LL << gPin,
71+
.pull_down_en = 0,
72+
.pull_up_en = 0,
73+
};
74+
res = gpio_config(&io_conf);
75+
if (res != ESP_OK) return res;
76+
gActive = false;
77+
return ESP_OK;
78+
}
79+
80+
esp_err_t ws2812_prepare_data(uint8_t *data, int len)
81+
{
82+
if (gBuffer != NULL) return ESP_FAIL;
83+
gBuffer = calloc(len * 8, sizeof(rmt_item32_t));
84+
if (gBuffer == NULL) return ESP_FAIL;
85+
gBufferLength = len * 8;
86+
for (uint32_t pos = 0; pos < len; pos++) {
87+
uint32_t mask = 1 << 7;
88+
for (uint8_t i = 0; i < 8; i++) {
89+
bool bit = data[pos] & mask;
90+
gBuffer[pos*8 + i] = bit ?
91+
(rmt_item32_t){{{T1H, 1, TL, 0}}} :
92+
(rmt_item32_t){{{T0H, 1, TL, 0}}};
93+
mask >>= 1;
94+
}
95+
}
96+
return ESP_OK;
97+
}
98+
99+
esp_err_t ws2812_free_data() {
100+
if (!gBuffer) return ESP_FAIL;
101+
free(gBuffer);
102+
gBuffer = NULL;
103+
gBufferLength = 0;
104+
return ESP_OK;
105+
}
106+
107+
esp_err_t ws2812_send_data(uint8_t *data, int len)
108+
{
109+
if (!gActive) return ESP_FAIL;
110+
esp_err_t res = ws2812_prepare_data(data, len);
111+
if (res != ESP_OK) return res;
112+
res = rmt_write_items(WS2812_RMT_CHANNEL, gBuffer, gBufferLength, false);
113+
if (res != ESP_OK) {
114+
ws2812_free_data();
115+
return res;
116+
}
117+
res = rmt_wait_tx_done(WS2812_RMT_CHANNEL, portMAX_DELAY);
118+
if (res != ESP_OK) {
119+
ws2812_free_data();
120+
return res;
121+
}
122+
res = ws2812_free_data();
123+
return res;
124+
}

0 commit comments

Comments
 (0)