Reputation: 2468
I'm hoping to make my raspiaudio muse proto play a sine wave for testing, but I only hear a very faint pulsation which doesn't even match with the output I expect.
Here's the whole code:
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_log.h"
#include "driver/uart.h"
#include "driver/i2s.h"
#include <math.h>
#include <vector>
#include <sstream>
#define I2S_BCLK 5
#define I2S_LRC 25
#define I2S_DOUT 26
#define I2S_DIN 35
/** This is necessary for the linker to find the firmware's entry point */
extern "C" {
void app_main(void);
}
#define SAMPLE_RATE (44100)
const i2s_port_t I2S_NUM = I2S_NUM_0;
#define PI (3.14159265)
#define FREQUENCY (440)
#define SAMPLES (SAMPLE_RATE / FREQUENCY)
typedef std::vector<int16_t> VectorBuffer;
VectorBuffer generate_sine_wave(
float sample_rate_Hz,
float duration_s = 1.0f,
float frequency = 440.0f,
float amplitude = 1.0f
) {
const auto samples_count = (int)(sample_rate_Hz * duration_s * 2);
VectorBuffer buffer(samples_count);
for (int i = 0; i < samples_count - 1; i++) {
const auto sample = (int16_t)(amplitude * sin((2 * PI * i * frequency) / sample_rate_Hz));
buffer.at(i) = sample;
buffer.at(i + 1) = sample;
}
return buffer;
}
// Should play a F note for half a second every second
void i2s_task(void *pvParameter) {
while (1) {
auto buffer = generate_sine_wave(
SAMPLE_RATE,
1.0f,
440.0f,
floor(INT16_MAX / 3)
);
ESP_LOGI("I2S_TASK", "Playing sine wave of %d samples", buffer.size());
size_t bytes_written;
for (;;) {
if (buffer.empty()) {
ESP_LOGD("I2S_TASK", "Buffer is empty, good.");
break;
}
esp_err_t e = i2s_write(I2S_NUM, buffer.data(), std::fmin(buffer.size(), 1024), &bytes_written, portMAX_DELAY);
if (e != ESP_OK) {
ESP_LOGE("I2S_TASK", "Error writing to I2S: %d", e);
break;
}
if (bytes_written == 0) {
// this should not happen
ESP_LOGE("I2S_TASK", "No bytes written");
break;
}
ESP_LOGI("I2S_TASK", "Wrote %d bytes", bytes_written);
/* Remove too verbose logging
std::ostringstream oss;
for (int i = 0; i < bytes_written; i++) {
oss << buffer.at(i) << " ";
}
ESP_LOGD("I2S_TASK", "Buffer: %s", oss.str().c_str());
// */
buffer.erase(buffer.begin(), buffer.begin() + bytes_written);
};
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
void hello_task(void *pvParameter) {
while (1) {
ESP_LOGI("HELLO_TASK", "hello");
vTaskDelay(500 / portTICK_PERIOD_MS);
}
}
void app_main() {
// UART configuration
const uart_config_t uart_config = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE
};
uart_param_config(UART_NUM_0, &uart_config);
uart_driver_install(UART_NUM_0, 1024 * 2, 0, 0, NULL, 0);
const auto mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX);
// I2S configuration
i2s_config_t i2s_config = {
mode,
.sample_rate = SAMPLE_RATE,
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
.communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_STAND_I2S | I2S_COMM_FORMAT_STAND_MSB),
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 3,
.dma_buf_len = 1024,
.use_apll = false,
.tx_desc_auto_clear = true,
.fixed_mclk = -1,
.mclk_multiple = I2S_MCLK_MULTIPLE_DEFAULT,
.bits_per_chan = I2S_BITS_PER_CHAN_16BIT,
};
// I2S pin configuration
i2s_pin_config_t pin_config = {
.bck_io_num = I2S_BCLK,
.ws_io_num = I2S_LRC,
.data_out_num = I2S_DOUT,
.data_in_num = I2S_DIN, // default Copilot was: I2S_PIN_NO_CHANGE // maybe 35 https://github.com/RASPIAUDIO/Simple_Bluetooth_Speaker_ESP32/blob/884c7f3700ec92dcf000dca75934860833559df7/speaker/speaker.ino#L171
};
// Install and start I2S driver
const auto e_i = i2s_driver_install(I2S_NUM, &i2s_config, 0, NULL);
if (e_i != ESP_OK) {
ESP_LOGE("APP_MAIN", "Error installing I2S driver: %d", e_i);
return;
}
const auto e_p = i2s_set_pin(I2S_NUM, &pin_config);
if (e_p != ESP_OK) {
ESP_LOGE("APP_MAIN", "Error setting I2S pin: %d", e_p);
return;
}
const auto e_s = i2s_start(I2S_NUM);
if (e_s != ESP_OK) {
ESP_LOGE("APP_MAIN", "Error starting I2S: %d", e_s);
return;
}
// Create the hello_task
xTaskCreate(&hello_task, "hello_task", 2048, NULL, 5, NULL);
// Create the i2s_task
xTaskCreate(&i2s_task, "i2s_task", 2048, NULL, 5, NULL);
}
Any idea?
Upvotes: 1
Views: 44