diff --git a/examples/peripherals/rmt/morse_code/CMakeLists.txt b/examples/peripherals/rmt/morse_code/CMakeLists.txt deleted file mode 100644 index 01ca83a100..0000000000 --- a/examples/peripherals/rmt/morse_code/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -# The following 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.5) - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(morse_code) diff --git a/examples/peripherals/rmt/morse_code/README.md b/examples/peripherals/rmt/morse_code/README.md deleted file mode 100644 index 3f799e857e..0000000000 --- a/examples/peripherals/rmt/morse_code/README.md +++ /dev/null @@ -1,66 +0,0 @@ -# RMT Transmit Example -- Morse Code - -(See the README.md file in the upper level 'examples' directory for more information about examples.) - -This example mainly illustrates how to transmit the [Morse code](https://en.wikipedia.org/wiki/Morse_code) using the RMT driver. - -## How to Use Example - -### Hardware Required - -* A development board with ESP32 SoC (e.g., ESP32-DevKitC, ESP-WROVER-KIT, etc.) -* A USB cable for Power supply and programming -* A LED, a speaker or an earphone - -Connection : - -``` - 330R LED -GPIO18 +----/\/\/\----+------|>|-----+ GND - | - | /| - +-+ | Speaker - | | | or - +-+ | earphone - | \| - | - +--------------+ GND -``` - -### Configure the Project - -Open the project configuration menu (`idf.py menuconfig`). - -In the `Example Configuration` menu: - -* Set the GPIO number used for transmitting the IR signal under `RMT TX GPIO` optin. - -### Build and Flash - -Run `idf.py -p PORT flash monitor` to build, flash and monitor the project. - -(To exit the serial monitor, type ``Ctrl-]``.) - -See the Getting Started Guide for all the steps to configure and use the ESP-IDF to build projects. - -* [ESP-IDF Getting Started Guide on ESP32](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/index.html) -* [ESP-IDF Getting Started Guide on ESP32-S2](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/get-started/index.html) -* [ESP-IDF Getting Started Guide on ESP32-C3](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/get-started/index.html) - - -## Example Output - -To be able to see and hear the message output by the RMT, connect an LED and a speaker or an earphone (be careful it might make a large noise) to the GPIO you set in the menuconfig. - -Run the example, you will see the following output log: - -``` bash -... -I (304) example: Configuring transmitter -I (2814) example: Transmission complete -... -``` - -## Troubleshooting - -For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon. diff --git a/examples/peripherals/rmt/morse_code/main/CMakeLists.txt b/examples/peripherals/rmt/morse_code/main/CMakeLists.txt deleted file mode 100644 index 870a4d9c71..0000000000 --- a/examples/peripherals/rmt/morse_code/main/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -idf_component_register(SRCS "morse_code_main.c" - INCLUDE_DIRS ".") diff --git a/examples/peripherals/rmt/morse_code/main/Kconfig.projbuild b/examples/peripherals/rmt/morse_code/main/Kconfig.projbuild deleted file mode 100644 index d596dcec79..0000000000 --- a/examples/peripherals/rmt/morse_code/main/Kconfig.projbuild +++ /dev/null @@ -1,7 +0,0 @@ -menu "Example Configuration" - config EXAMPLE_RMT_TX_GPIO - int "RMT TX GPIO" - default 18 - help - Set the GPIO number used for transmitting the RMT signal. -endmenu diff --git a/examples/peripherals/rmt/morse_code/main/morse_code_main.c b/examples/peripherals/rmt/morse_code/main/morse_code_main.c deleted file mode 100644 index d3066c8e54..0000000000 --- a/examples/peripherals/rmt/morse_code/main/morse_code_main.c +++ /dev/null @@ -1,80 +0,0 @@ -/* RMT example -- Morse Code - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ -#include "sdkconfig.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "esp_log.h" -#include "driver/rmt.h" - -static const char *TAG = "example"; - -#define RMT_TX_CHANNEL RMT_CHANNEL_0 - -/* - * Prepare a raw table with a message in the Morse code - * - * The message is "ESP" : . ... .--. - * - * The table structure represents the RMT item structure: - * {duration, level, duration, level} - * - */ -static const rmt_item32_t morse_esp[] = { - // E : dot - {{{ 32767, 1, 32767, 0 }}}, // dot - {{{ 32767, 0, 32767, 0 }}}, // SPACE - // S : dot, dot, dot - {{{ 32767, 1, 32767, 0 }}}, // dot - {{{ 32767, 1, 32767, 0 }}}, // dot - {{{ 32767, 1, 32767, 0 }}}, // dot - {{{ 32767, 0, 32767, 0 }}}, // SPACE - // P : dot, dash, dash, dot - {{{ 32767, 1, 32767, 0 }}}, // dot - {{{ 32767, 1, 32767, 1 }}}, - {{{ 32767, 1, 32767, 0 }}}, // dash - {{{ 32767, 1, 32767, 1 }}}, - {{{ 32767, 1, 32767, 0 }}}, // dash - {{{ 32767, 1, 32767, 0 }}}, // dot - // RMT end marker - {{{ 0, 1, 0, 0 }}} -}; - -/* - * Initialize the RMT Tx channel - */ -static void rmt_tx_init(void) -{ - rmt_config_t config = RMT_DEFAULT_CONFIG_TX(CONFIG_EXAMPLE_RMT_TX_GPIO, RMT_TX_CHANNEL); - // enable the carrier to be able to hear the Morse sound - // if the RMT_TX_GPIO is connected to a speaker - config.tx_config.carrier_en = true; - config.tx_config.carrier_duty_percent = 50; - // set audible career frequency of 611 Hz - // actually 611 Hz is the minimum, that can be set - // with current implementation of the RMT API - config.tx_config.carrier_freq_hz = 611; - // set the maximum clock divider to be able to output - // RMT pulses in range of about one hundred milliseconds - config.clk_div = 255; - - ESP_ERROR_CHECK(rmt_config(&config)); - ESP_ERROR_CHECK(rmt_driver_install(config.channel, 0, 0)); -} - -void app_main(void) -{ - ESP_LOGI(TAG, "Configuring transmitter"); - rmt_tx_init(); - - while (1) { - ESP_ERROR_CHECK(rmt_write_items(RMT_TX_CHANNEL, morse_esp, sizeof(morse_esp) / sizeof(morse_esp[0]), true)); - ESP_LOGI(TAG, "Transmission complete"); - vTaskDelay(1000 / portTICK_PERIOD_MS); - } -} diff --git a/examples/peripherals/rmt/musical_buzzer/README.md b/examples/peripherals/rmt/musical_buzzer/README.md index 32e3c551e8..82693d6aa8 100644 --- a/examples/peripherals/rmt/musical_buzzer/README.md +++ b/examples/peripherals/rmt/musical_buzzer/README.md @@ -1,41 +1,43 @@ -| Supported Targets | ESP32-S2 | ESP32-C3 | -| ----------------- | -------- | -------- | +| Supported Targets | ESP32-S2 | ESP32-C3 | ESP32-S3 | +| ----------------- | -------- | -------- | -------- | -# RMT Transmit Loop Example -- Musical Buzzer +# RMT Transmit Loop Count Example -- Musical Buzzer (See the README.md file in the upper level 'examples' directory for more information about examples.) -RMT peripheral can send customized RMT items in a loop, which means we can use it to generate a configurable length of periodic signal. +RMT tx channel can send symbols in a loop by hardware, which is useful to generate a variable length of periodic signal. -This example will show how to drive a passive buzzer to play a simple music, based on the RMT loop feature. +This example shows how to drive a passive buzzer to play a simple music. Each musical score is represented by a constant frequency of PWM with a constant duration. To play a music is to encoding the musical score continuously. An encoder called `score_encoder` is implemented in the example, it works as a simple wrapper of the `copy_encoder`. See [musical_score_encoder](main/musical_score_encoder.c) for details. ## How to Use Example ### Hardware Required -* A development board with ESP32-S2 SoC +* A development board with any supported Espressif SOC chip (see `Supported Targets` table above) * A USB cable for Power supply and programming -* A passive buzzer +* A **passive** buzzer Connection : ``` -VCC +--------------+ - | /+ - +++ | - | | | Passive Buzzer - +++ | - | \+ - | - + | - +<----+ -GPIO +--------+ - +-----+ - + | - | -GND +--------------+ + VCC+--------------+ + | /+ + +++ | + | | | Passive Buzzer + +++ | + | \+ + | + + | + +<----+ +RMT_BUZZER_GPIO+--------+ + +-----+ + + | + | + GND+--------------+ ``` +The GPIO number used in this example can be changed according to your board, by the macro `RMT_BUZZER_GPIO_NUM` defined in the [source file](main/musical_buzzer_example_main.c). + ### Build and Flash Run `idf.py -p PORT flash monitor` to build, flash and monitor the project. @@ -45,13 +47,18 @@ Run `idf.py -p PORT flash monitor` to build, flash and monitor the project. See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects. -## Example Output +## Console Output ``` -I (325) example: Playing Beethoven's Ode to joy +... +I (0) cpu_start: Starting scheduler on APP CPU. +I (318) example: Create RMT TX channel +I (338) example: Install musical score encoder +I (348) example: Playing Beethoven's Ode to joy... +... ``` -After you seeing this log, you should hear the music from your buzzer. You can also play other music by updating the `notation` array in the `musical_buzzer_example_main.c`. +After you seeing this log, you should hear the music from the buzzer. To play other music, you need to change the musical score array `score` defined in the [source file](main/musical_buzzer_example_main.c). The first member declares the frequency of one musical note, and the second member declares the duration that the note should last. ## Troubleshooting diff --git a/examples/peripherals/rmt/musical_buzzer/components/musical_buzzer/CMakeLists.txt b/examples/peripherals/rmt/musical_buzzer/components/musical_buzzer/CMakeLists.txt deleted file mode 100644 index 55d61201f3..0000000000 --- a/examples/peripherals/rmt/musical_buzzer/components/musical_buzzer/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -set(component_srcs "src/musical_buzzer_rmt.c") - -idf_component_register(SRCS "${component_srcs}" - INCLUDE_DIRS include - PRIV_REQUIRES driver) diff --git a/examples/peripherals/rmt/musical_buzzer/components/musical_buzzer/include/musical_buzzer.h b/examples/peripherals/rmt/musical_buzzer/components/musical_buzzer/include/musical_buzzer.h deleted file mode 100644 index c0a3892caa..0000000000 --- a/examples/peripherals/rmt/musical_buzzer/components/musical_buzzer/include/musical_buzzer.h +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#pragma once - -#include "esp_err.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Type of musical buzzer interface - * - */ -typedef struct musical_buzzer_t musical_buzzer_t; - -/** - * @brief Type of musical buzzer underlying device - * - */ -typedef void *musical_buzzer_dev_t; - -/** - * @brief Type of musical buzzer notation - * - */ -typedef struct { - uint32_t note_freq_hz; /*!< Note frequency, in Hz */ - uint32_t note_duration_ms; /*!< Note duration, in ms */ -} musical_buzzer_notation_t; - -/** - * @brief Declaration of musical buzzer interface - * - */ -struct musical_buzzer_t { - /** - * @brief Start to play the given notation - * - * @param buzzer musical buzzer handle - * @param notation music notation - * @param notation_len notation length - * @return - * - ESP_OK: Start playing notation successfully - * - ESP_ERR_INVALID_ARG: wrong parameter - */ - esp_err_t (*play)(musical_buzzer_t *buzzer, const musical_buzzer_notation_t *notation, uint32_t notation_len); - - /** - * @brief Stop playing - * - * @param buzzer musical buzzer handle - * @return - * - ESP_OK: Stop playing successfully - */ - esp_err_t (*stop)(musical_buzzer_t *buzzer); - - /** - * @brief Free memory used by musical buzzer - * - * @param buzzer musical buzzer handle - * @return - * - ESP_OK: Recycle memory successfully - */ - esp_err_t (*del)(musical_buzzer_t *buzzer); -}; - -typedef struct { - musical_buzzer_dev_t dev; /*!< Musical buzzer device (e.g. RMT channel, PWM channel, etc) */ - int flags; /*!< Extra flags */ -} musical_buzzer_config_t; - -/** - * @brief Default musical buzzer configuration - * - */ -#define MUSICAL_BUZZER_DEFAULT_CONFIG(dev_hdl) \ - { \ - .dev = dev_hdl, \ - .flags = 0, \ - } - -/** - * @brief Create musical buzzer instance based on RMT driver - * - * @param config musical buzzer configuration - * @param[out] ret_handle returned handle of musical buzzer instance - * @return - * - ESP_OK: create musical buzzer instance successfully - * - ESP_ERR_INVALID_ARG: wrong parameter - * - ESP_ERR_NO_MEM: no memory to allocate instance - */ -esp_err_t musical_buzzer_create_rmt(const musical_buzzer_config_t *config, musical_buzzer_t **ret_handle); - -#ifdef __cplusplus -} -#endif diff --git a/examples/peripherals/rmt/musical_buzzer/components/musical_buzzer/src/musical_buzzer_rmt.c b/examples/peripherals/rmt/musical_buzzer/components/musical_buzzer/src/musical_buzzer_rmt.c deleted file mode 100644 index e85e350ba6..0000000000 --- a/examples/peripherals/rmt/musical_buzzer/components/musical_buzzer/src/musical_buzzer_rmt.c +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#include -#include -#include -#include "esp_log.h" -#include "esp_attr.h" -#include "esp_compiler.h" -#include "driver/rmt.h" -#include "musical_buzzer.h" - -static const char *TAG = "buzzer_rmt"; - -#define BUZZER_CHECK(a, msg, tag, ret, ...) \ - do { \ - if (unlikely(!(a))) { \ - ESP_LOGE(TAG, "%s(%d): " msg, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ - ret_code = ret; \ - goto tag; \ - } \ - } while (0) - -typedef struct { - musical_buzzer_t parent; - rmt_channel_t channel; - uint32_t counter_clk_hz; - const musical_buzzer_notation_t *notation; - uint32_t notation_length; - uint32_t next_notation_index; -} rmt_buzzer_t; - -static IRAM_ATTR rmt_item32_t update_notation_freq_duration(rmt_buzzer_t *rmt_buzzer) -{ - rmt_item32_t notation_code = {.level0 = 1, .duration0 = 1, .level1 = 0, .duration1 = 1}; - const musical_buzzer_notation_t *notation = &rmt_buzzer->notation[rmt_buzzer->next_notation_index]; - - // convert frequency to RMT item format - notation_code.duration0 = rmt_buzzer->counter_clk_hz / notation->note_freq_hz / 2; - notation_code.duration1 = notation_code.duration0; - // convert duration to RMT loop count - rmt_set_tx_loop_count(rmt_buzzer->channel, notation->note_duration_ms * notation->note_freq_hz / 1000); - - rmt_buzzer->next_notation_index++; - return notation_code; -} - -static esp_err_t buzzer_play(musical_buzzer_t *buzzer, const musical_buzzer_notation_t *notation, uint32_t notation_length) -{ - esp_err_t ret_code = ESP_OK; - rmt_buzzer_t *rmt_buzzer = __containerof(buzzer, rmt_buzzer_t, parent); - - BUZZER_CHECK(notation, "notation can't be null", err, ESP_ERR_INVALID_ARG); - - // update notation with the new one - rmt_buzzer->notation = notation; - rmt_buzzer->next_notation_index = 0; - rmt_buzzer->notation_length = notation_length; - - rmt_item32_t notation_code = update_notation_freq_duration(rmt_buzzer); - // start TX - rmt_write_items(rmt_buzzer->channel, ¬ation_code, 1, false); -err: - return ret_code; -} - -static esp_err_t buzzer_stop(musical_buzzer_t *buzzer) -{ - rmt_buzzer_t *rmt_buzzer = __containerof(buzzer, rmt_buzzer_t, parent); - rmt_tx_stop(rmt_buzzer->channel); - return ESP_OK; -} - -static esp_err_t buzzer_del(musical_buzzer_t *buzzer) -{ - rmt_buzzer_t *rmt_buzzer = __containerof(buzzer, rmt_buzzer_t, parent); - free(rmt_buzzer); - return ESP_OK; -} - -static void rmt_tx_loop_end(rmt_channel_t channel, void *args) -{ - rmt_buzzer_t *rmt_buzzer = (rmt_buzzer_t *)args; - - // stop it firstly, RMT TX engine won't stop automatically in loop mode - rmt_tx_stop(rmt_buzzer->channel); - - // update rmt loop freq and duration if the notation doesn't reach the end - if (rmt_buzzer->next_notation_index < rmt_buzzer->notation_length) { - rmt_item32_t notation_code = update_notation_freq_duration(rmt_buzzer); - // issue a new TX transaction - rmt_write_items(rmt_buzzer->channel, ¬ation_code, 1, false); - } -} - -esp_err_t musical_buzzer_create_rmt(const musical_buzzer_config_t *config, musical_buzzer_t **ret_handle) -{ - esp_err_t ret_code = ESP_OK; - rmt_buzzer_t *rmt_buzzer = NULL; - BUZZER_CHECK(config, "configuration can't be null", err, ESP_ERR_INVALID_ARG); - BUZZER_CHECK(ret_handle, "can't assign handle to null", err, ESP_ERR_INVALID_ARG); - - rmt_buzzer = calloc(1, sizeof(rmt_buzzer_t)); - BUZZER_CHECK(rmt_buzzer, "allocate context memory failed", err, ESP_ERR_NO_MEM); - - rmt_buzzer->channel = (rmt_channel_t)config->dev; - - rmt_get_counter_clock(rmt_buzzer->channel, &rmt_buzzer->counter_clk_hz); - - // register tx end callback function, which got invoked when tx loop comes to the end - rmt_register_tx_end_callback(rmt_tx_loop_end, rmt_buzzer); - - rmt_buzzer->parent.del = buzzer_del; - rmt_buzzer->parent.play = buzzer_play; - rmt_buzzer->parent.stop = buzzer_stop; - - *ret_handle = &(rmt_buzzer->parent); - return ESP_OK; - -err: - if (rmt_buzzer) { - free(rmt_buzzer); - } - return ret_code; -} diff --git a/examples/peripherals/rmt/musical_buzzer/main/CMakeLists.txt b/examples/peripherals/rmt/musical_buzzer/main/CMakeLists.txt index 34c61acc67..6f8ea967c3 100644 --- a/examples/peripherals/rmt/musical_buzzer/main/CMakeLists.txt +++ b/examples/peripherals/rmt/musical_buzzer/main/CMakeLists.txt @@ -1,3 +1,2 @@ -idf_component_register(SRCS "musical_buzzer_example_main.c" - PRIV_REQUIRES musical_buzzer driver +idf_component_register(SRCS "musical_buzzer_example_main.c" "musical_score_encoder.c" INCLUDE_DIRS ".") diff --git a/examples/peripherals/rmt/musical_buzzer/main/musical_buzzer_example_main.c b/examples/peripherals/rmt/musical_buzzer/main/musical_buzzer_example_main.c index b77d5079e0..d79889b6f6 100644 --- a/examples/peripherals/rmt/musical_buzzer/main/musical_buzzer_example_main.c +++ b/examples/peripherals/rmt/musical_buzzer/main/musical_buzzer_example_main.c @@ -1,25 +1,22 @@ -/* RMT example -- Musical Buzzer +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ #include "esp_log.h" -#include "driver/rmt.h" -#include "musical_buzzer.h" +#include "driver/rmt_tx.h" +#include "musical_score_encoder.h" + +#define RMT_BUZZER_RESOLUTION_HZ 1000000 // 1MHz resolution +#define RMT_BUZZER_GPIO_NUM 0 static const char *TAG = "example"; -#define RMT_TX_CHANNEL RMT_CHANNEL_0 -#define RMT_TX_GPIO_NUM (4) - /** - * @brief Musical Notation: Beethoven's Ode to joy - * + * @brief Musical Score: Beethoven's Ode to joy */ -static const musical_buzzer_notation_t notation[] = { +static const buzzer_musical_score_t score[] = { {740, 400}, {740, 600}, {784, 400}, {880, 400}, {880, 400}, {784, 400}, {740, 400}, {659, 400}, {587, 400}, {587, 400}, {659, 400}, {740, 400}, @@ -43,21 +40,32 @@ static const musical_buzzer_notation_t notation[] = { void app_main(void) { - // Apply default RMT configuration - rmt_config_t dev_config = RMT_DEFAULT_CONFIG_TX(RMT_TX_GPIO_NUM, RMT_TX_CHANNEL); - dev_config.tx_config.loop_en = true; // Enable loop mode + ESP_LOGI(TAG, "Create RMT TX channel"); + rmt_channel_handle_t buzzer_chan = NULL; + rmt_tx_channel_config_t tx_chan_config = { + .clk_src = RMT_CLK_SRC_DEFAULT, // select source clock + .gpio_num = RMT_BUZZER_GPIO_NUM, + .mem_block_symbols = 64, + .resolution_hz = RMT_BUZZER_RESOLUTION_HZ, + .trans_queue_depth = 10, // set the maximum number of transactions that can pend in the background + }; + ESP_ERROR_CHECK(rmt_new_tx_channel(&tx_chan_config, &buzzer_chan)); - // Install RMT driver - ESP_ERROR_CHECK(rmt_config(&dev_config)); - ESP_ERROR_CHECK(rmt_driver_install(RMT_TX_CHANNEL, 0, 0)); + ESP_LOGI(TAG, "Install musical score encoder"); + rmt_encoder_handle_t score_encoder = NULL; + musical_score_encoder_config_t encoder_config = { + .resolution = RMT_BUZZER_RESOLUTION_HZ + }; + ESP_ERROR_CHECK(rmt_new_musical_score_encoder(&encoder_config, &score_encoder)); - // This example take the RMT channel number as the device handle - musical_buzzer_config_t buzzer_config = MUSICAL_BUZZER_DEFAULT_CONFIG((musical_buzzer_dev_t)RMT_TX_CHANNEL); - musical_buzzer_t *buzzer = NULL; - // Install buzzer driver - ESP_ERROR_CHECK(musical_buzzer_create_rmt(&buzzer_config, &buzzer)); + ESP_LOGI(TAG, "Enable RMT TX channel"); + ESP_ERROR_CHECK(rmt_enable(buzzer_chan)); + ESP_LOGI(TAG, "Playing Beethoven's Ode to joy..."); - ESP_LOGI(TAG, "Playing Beethoven's Ode to joy"); - - ESP_ERROR_CHECK(buzzer->play(buzzer, notation, sizeof(notation) / sizeof(notation[0]))); + for (size_t i = 0; i < sizeof(score) / sizeof(score[0]); i++) { + rmt_transmit_config_t tx_config = { + .loop_count = score[i].duration_ms * score[i].freq_hz / 1000, + }; + ESP_ERROR_CHECK(rmt_transmit(buzzer_chan, score_encoder, &score[i], sizeof(buzzer_musical_score_t), &tx_config)); + } } diff --git a/examples/peripherals/rmt/musical_buzzer/main/musical_score_encoder.c b/examples/peripherals/rmt/musical_buzzer/main/musical_score_encoder.c new file mode 100644 index 0000000000..a8f7574c0a --- /dev/null +++ b/examples/peripherals/rmt/musical_buzzer/main/musical_score_encoder.c @@ -0,0 +1,74 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp_check.h" +#include "musical_score_encoder.h" + +static const char *TAG = "score_encoder"; + +typedef struct { + rmt_encoder_t base; + rmt_encoder_t *copy_encoder; + uint32_t resolution; +} rmt_musical_score_encoder_t; + +static size_t rmt_encode_musical_score(rmt_encoder_t *encoder, rmt_channel_handle_t channel, const void *primary_data, size_t data_size, rmt_encode_state_t *ret_state) +{ + rmt_musical_score_encoder_t *score_encoder = __containerof(encoder, rmt_musical_score_encoder_t, base); + rmt_encoder_handle_t copy_encoder = score_encoder->copy_encoder; + rmt_encode_state_t session_state = 0; + buzzer_musical_score_t *score = (buzzer_musical_score_t *)primary_data; + uint32_t rmt_raw_symbol_duration = score_encoder->resolution / score->freq_hz / 2; + rmt_symbol_word_t musical_score_rmt_symbol = { + .level0 = 0, + .duration0 = rmt_raw_symbol_duration, + .level1 = 1, + .duration1 = rmt_raw_symbol_duration, + }; + size_t encoded_symbols = copy_encoder->encode(copy_encoder, channel, &musical_score_rmt_symbol, sizeof(musical_score_rmt_symbol), &session_state); + *ret_state = session_state; + return encoded_symbols; +} + +static esp_err_t rmt_del_musical_score_encoder(rmt_encoder_t *encoder) +{ + rmt_musical_score_encoder_t *score_encoder = __containerof(encoder, rmt_musical_score_encoder_t, base); + rmt_del_encoder(score_encoder->copy_encoder); + free(score_encoder); + return ESP_OK; +} + +static esp_err_t rmt_musical_score_encoder_reset(rmt_encoder_t *encoder) +{ + rmt_musical_score_encoder_t *score_encoder = __containerof(encoder, rmt_musical_score_encoder_t, base); + rmt_encoder_reset(score_encoder->copy_encoder); + return ESP_OK; +} + +esp_err_t rmt_new_musical_score_encoder(const musical_score_encoder_config_t *config, rmt_encoder_handle_t *ret_encoder) +{ + esp_err_t ret = ESP_OK; + rmt_musical_score_encoder_t *score_encoder = NULL; + ESP_GOTO_ON_FALSE(config && ret_encoder, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); + score_encoder = calloc(1, sizeof(rmt_musical_score_encoder_t)); + ESP_GOTO_ON_FALSE(score_encoder, ESP_ERR_NO_MEM, err, TAG, "no mem for musical score encoder"); + score_encoder->base.encode = rmt_encode_musical_score; + score_encoder->base.del = rmt_del_musical_score_encoder; + score_encoder->base.reset = rmt_musical_score_encoder_reset; + score_encoder->resolution = config->resolution; + rmt_copy_encoder_config_t copy_encoder_config = {}; + ESP_GOTO_ON_ERROR(rmt_new_copy_encoder(©_encoder_config, &score_encoder->copy_encoder), err, TAG, "create copy encoder failed"); + *ret_encoder = &score_encoder->base; + return ESP_OK; +err: + if (score_encoder) { + if (score_encoder->copy_encoder) { + rmt_del_encoder(score_encoder->copy_encoder); + } + free(score_encoder); + } + return ret; +} diff --git a/examples/peripherals/rmt/musical_buzzer/main/musical_score_encoder.h b/examples/peripherals/rmt/musical_buzzer/main/musical_score_encoder.h new file mode 100644 index 0000000000..26c9050ef7 --- /dev/null +++ b/examples/peripherals/rmt/musical_buzzer/main/musical_score_encoder.h @@ -0,0 +1,44 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include "driver/rmt_encoder.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Type of buzzer musical score + */ +typedef struct { + uint32_t freq_hz; /*!< Frequency, in Hz */ + uint32_t duration_ms; /*!< Duration, in ms */ +} buzzer_musical_score_t; + +/** + * @brief Type of musical score encoder configuration + */ +typedef struct { + uint32_t resolution; /*!< Encoder resolution, in Hz */ +} musical_score_encoder_config_t; + +/** + * @brief Create RMT encoder for encoding musical score into RMT symbols + * + * @param[in] config Encoder configuration + * @param[out] ret_encoder Returned encoder handle + * @return + * - ESP_ERR_INVALID_ARG for any invalid arguments + * - ESP_ERR_NO_MEM out of memory when creating musical score encoder + * - ESP_OK if creating encoder successfully + */ +esp_err_t rmt_new_musical_score_encoder(const musical_score_encoder_config_t *config, rmt_encoder_handle_t *ret_encoder); + +#ifdef __cplusplus +} +#endif diff --git a/examples/peripherals/rmt/musical_buzzer/pytest_musical_buzzer.py b/examples/peripherals/rmt/musical_buzzer/pytest_musical_buzzer.py new file mode 100644 index 0000000000..81e13534ac --- /dev/null +++ b/examples/peripherals/rmt/musical_buzzer/pytest_musical_buzzer.py @@ -0,0 +1,16 @@ +# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: CC0-1.0 + +import pytest +from pytest_embedded import Dut + + +@pytest.mark.esp32s2 +@pytest.mark.esp32s3 +@pytest.mark.esp32c3 +@pytest.mark.generic +def test_musical_buzzer_example(dut: Dut) -> None: + dut.expect_exact('example: Create RMT TX channel') + dut.expect_exact('example: Install musical score encoder') + dut.expect_exact('example: Enable RMT TX channel') + dut.expect_exact("example: Playing Beethoven's Ode to joy") diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index 79c6888494..fb5573713b 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -2072,10 +2072,6 @@ examples/peripherals/mcpwm/mcpwm_brushed_dc_control/main/mcpwm_brushed_dc_contro examples/peripherals/mcpwm/mcpwm_capture_hc_sr04/main/mcpwm_capture_hc_sr04.c examples/peripherals/mcpwm/mcpwm_servo_control/main/mcpwm_servo_control_example_main.c examples/peripherals/mcpwm/mcpwm_sync_example/main/mcpwm_sync_example.c -examples/peripherals/rmt/morse_code/main/morse_code_main.c -examples/peripherals/rmt/musical_buzzer/components/musical_buzzer/include/musical_buzzer.h -examples/peripherals/rmt/musical_buzzer/components/musical_buzzer/src/musical_buzzer_rmt.c -examples/peripherals/rmt/musical_buzzer/main/musical_buzzer_example_main.c examples/peripherals/sdio/host/main/app_main.c examples/peripherals/sdio/sdio_test.py examples/peripherals/sdio/slave/main/app_main.c