├── component.mk ├── CMakeLists.txt ├── README.md ├── .gitignore.txt ├── include └── ws2812.h └── ws2812.c /component.mk: -------------------------------------------------------------------------------- 1 | # Use defaults 2 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #idf_component_register(SRCS "ws2812.c" INCLUDE_DIRS include) 2 | 3 | set(COMPONENT_ADD_INCLUDEDIRS include) 4 | set(COMPONENT_SRCS "ws2812.c") 5 | register_component() 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | This ESP32 component was created since I was unable to find a suitable WS2812 library to control an 'x' amount of leds using I2S for the esp-idf sdk. The code has been tested in a personal project. 4 | 5 | # Usage 6 | 7 | Currently it defaults to GPIO 25 for up to 8 leds. The settings can be changed in `ws2812.h`. 8 | 9 | # Todo 10 | 11 | - Support for RGBW leds 12 | - Configuration through init + memory allocation 13 | 14 | ## License 15 | 16 | The code in this project is licensed under the MIT licence. -------------------------------------------------------------------------------- /.gitignore.txt: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Linker output 11 | *.ilk 12 | *.map 13 | *.exp 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Libraries 20 | *.lib 21 | *.a 22 | *.la 23 | *.lo 24 | 25 | # Shared objects (inc. Windows DLLs) 26 | *.dll 27 | *.so 28 | *.so.* 29 | *.dylib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.i*86 36 | *.x86_64 37 | *.hex 38 | 39 | # Debug files 40 | *.dSYM/ 41 | *.su 42 | *.idb 43 | *.pdb 44 | 45 | # Kernel Module Compile Results 46 | *.mod* 47 | *.cmd 48 | .tmp_versions/ 49 | modules.order 50 | Module.symvers 51 | Mkfile.old 52 | dkms.conf 53 | -------------------------------------------------------------------------------- /include/ws2812.h: -------------------------------------------------------------------------------- 1 | /** MIT licence 2 | 3 | Copyright (C) 2019 by Vu Nam https://github.com/vunam https://studiokoda.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: The above copyright notice and this 11 | permission notice shall be included in all copies or substantial portions of 12 | the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 17 | EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES 18 | OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | DEALINGS IN THE SOFTWARE. 21 | 22 | */ 23 | 24 | #ifndef WS2812_H 25 | #define WS2812_H 26 | 27 | #include 28 | #include 29 | 30 | #define LED_NUMBER 8 31 | #define PIXEL_SIZE 12 // each colour takes 4 bytes 32 | #define SAMPLE_RATE (93750) 33 | #define ZERO_BUFFER 48 34 | #define I2S_NUM (0) 35 | #define I2S_DO_IO (GPIO_NUM_25) 36 | #define I2S_DI_IO (-1) 37 | 38 | typedef struct { 39 | uint8_t green; 40 | uint8_t red; 41 | uint8_t blue; 42 | } ws2812_pixel_t; 43 | 44 | void ws2812_init(); 45 | 46 | void ws2812_update(ws2812_pixel_t *pixels); 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /ws2812.c: -------------------------------------------------------------------------------- 1 | /** MIT licence 2 | 3 | Copyright (C) 2019 by Vu Nam https://github.com/vunam https://studiokoda.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: The above copyright notice and this 11 | permission notice shall be included in all copies or substantial portions of 12 | the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 17 | EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES 18 | OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | DEALINGS IN THE SOFTWARE. 21 | 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | #include "freertos/FreeRTOS.h" 28 | #include "freertos/task.h" 29 | #include "esp_system.h" 30 | #include "driver/i2s.h" 31 | #include "ws2812.h" 32 | 33 | i2s_config_t i2s_config = { 34 | .mode = I2S_MODE_MASTER | I2S_MODE_TX, 35 | .sample_rate = SAMPLE_RATE, 36 | .bits_per_sample = 16, 37 | .communication_format = I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB, 38 | .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, 39 | .intr_alloc_flags = 0, 40 | .dma_buf_count = 4, 41 | .use_apll = false, 42 | }; 43 | 44 | i2s_pin_config_t pin_config = {.bck_io_num = -1, 45 | .ws_io_num = -1, 46 | .data_out_num = I2S_DO_IO, 47 | .data_in_num = -1}; 48 | 49 | static uint8_t out_buffer[LED_NUMBER * PIXEL_SIZE] = {0}; 50 | static uint8_t off_buffer[ZERO_BUFFER] = {0}; 51 | static uint16_t size_buffer; 52 | 53 | static const uint16_t bitpatterns[4] = {0x88, 0x8e, 0xe8, 0xee}; 54 | 55 | void ws2812_init() { 56 | size_buffer = LED_NUMBER * PIXEL_SIZE; 57 | 58 | i2s_config.dma_buf_len = size_buffer; 59 | 60 | i2s_driver_install(I2S_NUM, &i2s_config, 0, NULL); 61 | i2s_set_pin(I2S_NUM, &pin_config); 62 | } 63 | 64 | void ws2812_update(ws2812_pixel_t *pixels) { 65 | size_t bytes_written = 0; 66 | 67 | for (uint16_t i = 0; i < LED_NUMBER; i++) { 68 | int loc = i * PIXEL_SIZE; 69 | 70 | out_buffer[loc] = bitpatterns[pixels[i].green >> 6 & 0x03]; 71 | out_buffer[loc + 1] = bitpatterns[pixels[i].green >> 4 & 0x03]; 72 | out_buffer[loc + 2] = bitpatterns[pixels[i].green >> 2 & 0x03]; 73 | out_buffer[loc + 3] = bitpatterns[pixels[i].green & 0x03]; 74 | 75 | out_buffer[loc + 4] = bitpatterns[pixels[i].red >> 6 & 0x03]; 76 | out_buffer[loc + 5] = bitpatterns[pixels[i].red >> 4 & 0x03]; 77 | out_buffer[loc + 6] = bitpatterns[pixels[i].red >> 2 & 0x03]; 78 | out_buffer[loc + 7] = bitpatterns[pixels[i].red & 0x03]; 79 | 80 | out_buffer[loc + 8] = bitpatterns[pixels[i].blue >> 6 & 0x03]; 81 | out_buffer[loc + 9] = bitpatterns[pixels[i].blue >> 4 & 0x03]; 82 | out_buffer[loc + 10] = bitpatterns[pixels[i].blue >> 2 & 0x03]; 83 | out_buffer[loc + 11] = bitpatterns[pixels[i].blue & 0x03]; 84 | } 85 | 86 | i2s_write(I2S_NUM, out_buffer, size_buffer, &bytes_written, portMAX_DELAY); 87 | i2s_write(I2S_NUM, off_buffer, ZERO_BUFFER, &bytes_written, portMAX_DELAY); 88 | vTaskDelay(pdMS_TO_TICKS(10)); 89 | i2s_zero_dma_buffer(I2S_NUM); 90 | } 91 | --------------------------------------------------------------------------------