/*
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <sys/unistd.h>
#include <sys/stat.h>
#include "esp_log.h"
#include "esp_err.h"
#include "esp_system.h"
#include "esp_vfs_fat.h"
#include "driver/spi_common.h"
#include "sdmmc_cmd.h"
#include "format_wav.h"
#include "hal/i2s_types.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/i2s_std.h"
#include "driver/gpio.h"
#include "esp_check.h"
#include "sdkconfig.h"
#include "app_fft.h"
#include "freertos/queue.h"
#include "nvs_flash.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "protocol_examples_common.h"
#include "esp_log.h"
#include "app_ntp.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "app_http.h"
#define LED_PIN 2
// extern char frequency[10];
// extern char description[50];
// extern char status[20];
// extern float *frequency_samples;
float current_frequency_value_A = 0.0;
float current_frequency_value_B = 0.0;
float current_frequency_value_C = 0.0;
float current_frequency_value_D = 0.0;
float current_frequency_value_E = 0.0;
float previous_frequency_value_A = 0.0;
float previous_frequency_value_B = 0.0;
float previous_frequency_value_C = 0.0;
float previous_frequency_value_D = 0.0;
float previous_frequency_value_E = 0.0;
float previous_max_frequency = 0.0;
char description_A[50] = "Calling endpoint A";
char description_B[50] = "Calling endpoint B";
char description_C[50] = "Calling endpoint C";
char description_D[50] = "Calling endpoint D";
char description_E[50] = "Calling endpoint E";
char type_A[20] = "status_01";
char type_B[20] = "status_02";
char type_C[20] = "status_03";
char type_D[20] = "status_04";
char type_E[20] = "status_05";
char status[20] = "Active";
#define BUFF_SIZE 1024
#define BYTE_RATE (CONFIG_SAMPLE_RATE * 4)
size_t bytes_read = 0;
int32_t raw_samples[BUFF_SIZE] = {0};
static const char *TAG = "Voice Recorder";
#define SPI_DMA_CHAN SPI_DMA_CH_AUTO
#define SD_MOUNT_POINT "/sdcard"
sdmmc_host_t host = SDSPI_HOST_DEFAULT();
sdmmc_card_t *card;
static i2s_chan_handle_t rx_chan; // I2S rx channel handler
QueueHandle_t sample_queue, frequency_queue;
void app_connect_wifi(void)
{
nvs_flash_init();
esp_netif_init();
esp_event_loop_create_default();
example_connect();
}
static void fft_task(void *args)
{
int32_t fft_samples[BUFF_SIZE] = {0};
while (1)
{
// Receive data from the queue
if (xQueueReceive(sample_queue, (void *)fft_samples, portMAX_DELAY) == pdTRUE)
{
compute_fft(fft_samples);
}
vTaskDelay(pdMS_TO_TICKS(80));
// printf("executing compute fft \n");
}
vTaskDelete(NULL);
}
void record_wav(uint32_t rec_time)
{
// Use POSIX and C standard library functions to work with files.
int flash_wr_size = 0;
char file_path[100] = {0};
create_file_with_timestamp(file_path, sizeof(file_path));
printf("********** %s ************\n", file_path);
ESP_LOGI(TAG, "Opening file");
uint32_t flash_rec_time = BYTE_RATE * rec_time;
const wav_header_t wav_header =
WAV_HEADER_PCM_DEFAULT(flash_rec_time, 32, CONFIG_SAMPLE_RATE, 1);
// First check if file exists before creating a new file.
struct stat st;
if (stat(file_path, &st) == 0)
{
printf("inside unlink if \n");
// Delete it if it exists
unlink(file_path);
}
// printf("outside unlink if \n");
// Create new WAV file
FILE *f = fopen(file_path, "a");
if (f == NULL)
{
ESP_LOGE(TAG, "Failed to open file for writing");
return;
}
// Write the header to the WAV file
fwrite(&wav_header, sizeof(wav_header), 1, f);
i2s_channel_enable(rx_chan);
gpio_set_level(LED_PIN, 1);
ESP_LOGI(TAG, "Starting recording for %d seconds!", CONFIG_REC_TIME);
// Start recording
while (flash_wr_size < flash_rec_time)
{
size_t bytes_read = 0;
// Read the RAW samples from the microphone
i2s_channel_read(rx_chan, raw_samples, sizeof(int32_t) * BUFF_SIZE, &bytes_read, portMAX_DELAY);
int samples_read = bytes_read / 4;
if (samples_read == BUFF_SIZE)
{
// Send data to the queue
if (xQueueSend(sample_queue, (void *)raw_samples, portMAX_DELAY) != pdTRUE)
{
printf("Failed to send data to queue\n");
}
}
fwrite(raw_samples, bytes_read, 1, f);
flash_wr_size += bytes_read;
}
gpio_set_level(LED_PIN, 0);
ESP_LOGI(TAG, "Recording done!");
fclose(f);
ESP_LOGI(TAG, "File written on SDCard");
// All done, unmount partition and disable SPI peripheral
// esp_vfs_fat_sdcard_unmount(SD_MOUNT_POINT, card);
// ESP_LOGI(TAG, "Card unmounted");
// Deinitialize the bus after all devices are removed
// spi_bus_free(host.slot);
// call_endpoints();
current_frequency_value_A = 0.0;
current_frequency_value_B = 0.0;
current_frequency_value_C = 0.0;
current_frequency_value_D = 0.0;
current_frequency_value_E = 0.0;
previous_frequency_value_A = 0.0;
previous_frequency_value_B = 0.0;
previous_frequency_value_C = 0.0;
previous_frequency_value_D = 0.0;
previous_frequency_value_E = 0.0;
previous_max_frequency = 0.0;
}
static void record_wave_task(void *args)
{
while (1)
{
record_wav(CONFIG_REC_TIME);
ESP_ERROR_CHECK(i2s_channel_disable(rx_chan));
// ESP_ERROR_CHECK(i2s_del_channel(rx_chan));
/// vTaskDelete(NULL);
vTaskDelay(pdMS_TO_TICKS(5000));
}
}
static void freq_task(void *args)
{
float frequency_rcv_sample;
while (1)
{
if (xQueueReceive(frequency_queue, &frequency_rcv_sample, pdMS_TO_TICKS(1000)) == pdPASS)
{
call_endpoints(frequency_rcv_sample);
}
vTaskDelay(pdMS_TO_TICKS(80));
}
}
void mount_sdcard(void)
{
esp_err_t ret;
// Options for mounting the filesystem.
// If format_if_mount_failed is set to true, SD card will be partitioned and
// formatted in case when mounting fails.
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
.format_if_mount_failed = true,
.max_files = 5,
.allocation_unit_size = 8 * 1024};
ESP_LOGI(TAG, "Initializing SD card");
host.max_freq_khz = 1000;
spi_bus_config_t bus_cfg = {
.mosi_io_num = CONFIG_SPI_MOSI_GPIO,
.miso_io_num = CONFIG_SPI_MISO_GPIO,
.sclk_io_num = CONFIG_SPI_SCLK_GPIO,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = 4000,
};
ret = spi_bus_initialize(host.slot, &bus_cfg, SPI_DMA_CHAN);
if (ret != ESP_OK)
{
ESP_LOGE(TAG, "Failed to initialize bus.");
return;
}
// This initializes the slot without card detect (CD) and write protect (WP) signals.
// Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals.
sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT();
slot_config.gpio_cs = CONFIG_SPI_CS_GPIO;
slot_config.host_id = host.slot;
ret = esp_vfs_fat_sdspi_mount(SD_MOUNT_POINT, &host, &slot_config, &mount_config, &card);
if (ret != ESP_OK)
{
if (ret == ESP_FAIL)
{
ESP_LOGE(TAG, "Failed to mount filesystem.");
}
else
{
ESP_LOGE(TAG, "Failed to initialize the card (%s). "
"Make sure SD card lines have pull-up resistors in place.",
esp_err_to_name(ret));
}
return;
}
// Card has been initialized, print its properties
sdmmc_card_print_info(stdout, card);
}
static void i2s_init_std_simplex(void)
{
i2s_chan_config_t rx_chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_AUTO, I2S_ROLE_MASTER);
ESP_ERROR_CHECK(i2s_new_channel(&rx_chan_cfg, NULL, &rx_chan));
i2s_std_config_t rx_std_cfg = {
.clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(CONFIG_SAMPLE_RATE),
.slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_32BIT, I2S_SLOT_MODE_MONO),
.gpio_cfg = {
.mclk = I2S_GPIO_UNUSED, // some codecs may require mclk signal, this example doesn't need it
.bclk = CONFIG_I2S_BCLK_GPIO,
.ws = CONFIG_I2S_WS_GPIO,
.dout = I2S_GPIO_UNUSED,
.din = CONFIG_I2S_DIN_GPIO,
.invert_flags = {
.mclk_inv = false,
.bclk_inv = false,
.ws_inv = false,
},
},
};
rx_std_cfg.slot_cfg.slot_mask = I2S_STD_SLOT_RIGHT;
ESP_ERROR_CHECK(i2s_channel_init_std_mode(rx_chan, &rx_std_cfg));
}
void app_main(void)
{
gpio_set_direction(LED_PIN, GPIO_MODE_OUTPUT);
// Mount the SDCard for recording the audio file
sample_queue = xQueueCreate(10, BUFF_SIZE * sizeof(int32_t));
frequency_queue = xQueueCreate(2048, sizeof(float));
if (sample_queue == NULL)
{
printf("Failed to create sample queue\n");
return;
}
if (frequency_queue == NULL)
{
printf("Failed to create frequency queue\n");
return;
}
app_connect_wifi();
app_ntp_client_init();
app_fft_init();
mount_sdcard();
// Acquire a I2S philips channel for the IMP441 microphone
i2s_init_std_simplex();
xTaskCreate(record_wave_task, "i2s_example_read_task", 32384, NULL, 5, NULL);
xTaskCreate(fft_task, "fft_task", 8096, NULL, 5, NULL);
xTaskCreate(freq_task, "frequency task", 32384, NULL, 5, NULL);
}
Comments
Please log in or sign up to comment.