example: update musical buzzer example with new rmt driver

This commit is contained in:
morris
2022-04-07 13:13:28 +08:00
parent d537da5bfb
commit b3c1480d9c
15 changed files with 203 additions and 468 deletions

View File

@@ -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)

View File

@@ -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.

View File

@@ -1,2 +0,0 @@
idf_component_register(SRCS "morse_code_main.c"
INCLUDE_DIRS ".")

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -1,5 +0,0 @@
set(component_srcs "src/musical_buzzer_rmt.c")
idf_component_register(SRCS "${component_srcs}"
INCLUDE_DIRS include
PRIV_REQUIRES driver)

View File

@@ -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

View File

@@ -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 <stdlib.h>
#include <string.h>
#include <sys/cdefs.h>
#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, &notation_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, &notation_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;
}

View File

@@ -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 ".")

View File

@@ -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));
}
}

View File

@@ -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(&copy_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;
}

View File

@@ -0,0 +1,44 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#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

View File

@@ -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")

View File

@@ -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