diff --git a/build_config.yml b/build_config.yml index 5b2531e..b2fe223 100644 --- a/build_config.yml +++ b/build_config.yml @@ -99,6 +99,14 @@ projects: idf_version: release-v5.4 target: esp32s3 + - path: examples/peripherals/rmt/rmt_simple_tx + idf_version: release-v5.4 + target: esp32s3 + + - path: examples/peripherals/rmt/ws2812_simple_encoder + idf_version: release-v5.4 + target: esp32s3 + - path: examples/peripherals/spi/spi_basic idf_version: release-v5.4 target: esp32s3 diff --git a/examples/peripherals/rmt/rmt_simple_tx/CMakeLists.txt b/examples/peripherals/rmt/rmt_simple_tx/CMakeLists.txt new file mode 100644 index 0000000..1f47dcf --- /dev/null +++ b/examples/peripherals/rmt/rmt_simple_tx/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following five lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(rmt_simple_tx) diff --git a/examples/peripherals/rmt/rmt_simple_tx/main/CMakeLists.txt b/examples/peripherals/rmt/rmt_simple_tx/main/CMakeLists.txt new file mode 100644 index 0000000..cf2c455 --- /dev/null +++ b/examples/peripherals/rmt/rmt_simple_tx/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "main.c" + INCLUDE_DIRS ".") diff --git a/examples/peripherals/rmt/rmt_simple_tx/main/main.c b/examples/peripherals/rmt/rmt_simple_tx/main/main.c new file mode 100644 index 0000000..92b77f5 --- /dev/null +++ b/examples/peripherals/rmt/rmt_simple_tx/main/main.c @@ -0,0 +1,51 @@ +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "driver/rmt_tx.h" + +void app_main(void) +{ + rmt_tx_channel_config_t tx_channel_cfg = { + .mem_block_symbols = SOC_RMT_MEM_WORDS_PER_CHANNEL, + .clk_src = RMT_CLK_SRC_DEFAULT, + .resolution_hz = 1 * 1000 * 1000, // 1MHz, 1 tick = 1us + .trans_queue_depth = 4, + .gpio_num = GPIO_NUM_4, + .intr_priority = 3 + }; + rmt_channel_handle_t tx_channel = NULL; + rmt_new_tx_channel(&tx_channel_cfg, &tx_channel); + + rmt_encoder_handle_t bytes_encoder = NULL; + + // Encode bit 0 and 1 + rmt_bytes_encoder_config_t bytes_enc_config = { + .bit0 = { + .level0 = 1, + .duration0 = 1, // 1us + .level1 = 0, + .duration1 = 1, // 1us + }, // For bit 0: first high level for 1us, then low level for 1us + .bit1 = { + .level0 = 1, + .duration0 = 9, // 9us + .level1 = 0, + .duration1 = 3, // 3us + }, // For bit 1: first high level for 9us, then low level for 3us + }; + + rmt_new_bytes_encoder(&bytes_enc_config, &bytes_encoder); + rmt_enable(tx_channel); + + rmt_transmit_config_t transmit_config = { + .loop_count = 0, // no loop + }; + + while (1) { + rmt_transmit(tx_channel, bytes_encoder, (uint8_t[]) { + 0x05 + }, 1, &transmit_config); // For 0x05, it's actually 8-bit data, corresponding to 0000 0101 + vTaskDelay(500 / portTICK_PERIOD_MS); + } +} diff --git a/examples/peripherals/rmt/rmt_simple_tx/sdkconfig.defaults b/examples/peripherals/rmt/rmt_simple_tx/sdkconfig.defaults new file mode 100644 index 0000000..fd0422c --- /dev/null +++ b/examples/peripherals/rmt/rmt_simple_tx/sdkconfig.defaults @@ -0,0 +1,4 @@ +CONFIG_IDF_TARGET="esp32s3" +CONFIG_IDF_TARGET_ESP32S3=y + +CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y diff --git a/examples/peripherals/rmt/ws2812_simple_encoder/CMakeLists.txt b/examples/peripherals/rmt/ws2812_simple_encoder/CMakeLists.txt new file mode 100644 index 0000000..609fdda --- /dev/null +++ b/examples/peripherals/rmt/ws2812_simple_encoder/CMakeLists.txt @@ -0,0 +1,8 @@ +# For more information about build system see +# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html +# The following five lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(ws2812_simple_encoder) diff --git a/examples/peripherals/rmt/ws2812_simple_encoder/main/CMakeLists.txt b/examples/peripherals/rmt/ws2812_simple_encoder/main/CMakeLists.txt new file mode 100644 index 0000000..cf2c455 --- /dev/null +++ b/examples/peripherals/rmt/ws2812_simple_encoder/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "main.c" + INCLUDE_DIRS ".") diff --git a/examples/peripherals/rmt/ws2812_simple_encoder/main/main.c b/examples/peripherals/rmt/ws2812_simple_encoder/main/main.c new file mode 100644 index 0000000..7f2a147 --- /dev/null +++ b/examples/peripherals/rmt/ws2812_simple_encoder/main/main.c @@ -0,0 +1,102 @@ +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "driver/rmt_tx.h" +#include "esp_log.h" + +static const char *TAG = "WS2812"; + +static const rmt_symbol_word_t ws2812_zero = { + .level0 = 1, + .duration0 = 4, /*!< 0.4us */ + .level1 = 0, + .duration1 = 9, /*!< 0.9us */ +}; + +static const rmt_symbol_word_t ws2812_one = { + .level0 = 1, + .duration0 = 9, /*!< 0.9us */ + .level1 = 0, + .duration1 = 3, /*!< 0.4us */ +}; + +static const rmt_symbol_word_t ws2812_reset = { + .level0 = 0, + .duration0 = 250, /*!< 25us */ + .level1 = 0, + .duration1 = 250, /*!< 25us */ +}; + +static size_t encoder_callback(const void *data, size_t data_size, + size_t symbols_written, size_t symbols_free, + rmt_symbol_word_t *symbols, bool *done, void *arg) +{ + if (symbols_free < 8) { + return 0; /*!< Need at least 8 symbols to form one byte */ + } + printf("symbols_written:%d,data_size:%d\n", symbols_written, data_size); + + size_t data_pos = symbols_written / 8; /*!< Calculate current byte position, assuming input is {0xFF, 0x00, 0x00}, data_size is 3, each byte written increments symbols_written by 8 */ + uint8_t *data_bytes = (uint8_t *)data; + + if (data_pos < data_size) { + size_t symbol_pos = 0; + for (int bitmask = 0x80; bitmask != 0; bitmask >>= 1) { + if (data_bytes[data_pos] & bitmask) { + symbols[symbol_pos++] = ws2812_one; + } else { + symbols[symbol_pos++] = ws2812_zero; + } + } + + return symbol_pos; + } else { + symbols[0] = ws2812_reset; + *done = 1; + return 1; + } +} + +void app_main(void) +{ + rmt_channel_handle_t led_chan = NULL; + rmt_tx_channel_config_t tx_chan_config = { + .mem_block_symbols = 64, + .clk_src = RMT_CLK_SRC_DEFAULT, + .resolution_hz = 10 * 1000 * 1000, // 10MHz, 1 tick = 0.1us + .trans_queue_depth = 4, + .gpio_num = GPIO_NUM_38, + .intr_priority = 3 + }; + + ESP_ERROR_CHECK(rmt_new_tx_channel(&tx_chan_config, &led_chan)); + + ESP_LOGI(TAG, "Create simple callback-based encoder"); + rmt_encoder_handle_t simple_encoder = NULL; + const rmt_simple_encoder_config_t simple_encoder_cfg = { + .callback = encoder_callback + // Note we don't set min_chunk_size here as the default of 64 is good enough. + }; + ESP_ERROR_CHECK(rmt_new_simple_encoder(&simple_encoder_cfg, &simple_encoder)); + + ESP_LOGI(TAG, "Enable RMT TX channel"); + ESP_ERROR_CHECK(rmt_enable(led_chan)); + + ESP_LOGI(TAG, "Start LED rainbow chase"); + rmt_transmit_config_t tx_config = { + .loop_count = 0, // no transfer loop + }; + + // WS2812 encoding is GRB + uint8_t red[3] = {0x00, 0xFF, 0x00}; /*!< R */ + rmt_transmit(led_chan, simple_encoder, red, sizeof(red), &tx_config); + vTaskDelay(1000 / portTICK_PERIOD_MS); + + uint8_t green[3] = {0xFF, 0x00, 0x00}; /*!< G */ + rmt_transmit(led_chan, simple_encoder, green, sizeof(green), &tx_config); + vTaskDelay(1000 / portTICK_PERIOD_MS); + + uint8_t blue[3] = {0x00, 0x00, 0xFF}; /*!< B */ + rmt_transmit(led_chan, simple_encoder, blue, sizeof(blue), &tx_config); +} diff --git a/examples/peripherals/rmt/ws2812_simple_encoder/sdkconfig.defaults b/examples/peripherals/rmt/ws2812_simple_encoder/sdkconfig.defaults new file mode 100644 index 0000000..fd0422c --- /dev/null +++ b/examples/peripherals/rmt/ws2812_simple_encoder/sdkconfig.defaults @@ -0,0 +1,4 @@ +CONFIG_IDF_TARGET="esp32s3" +CONFIG_IDF_TARGET_ESP32S3=y + +CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y