Skip to content

Instantly share code, notes, and snippets.

@Roman-Port
Last active April 20, 2022 20:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Roman-Port/4ac24ee780f6836a9ec17c1f869c1c7f to your computer and use it in GitHub Desktop.
Save Roman-Port/4ac24ee780f6836a9ec17c1f869c1c7f to your computer and use it in GitHub Desktop.
#include <string.h>
#include <sys/unistd.h>
#include <sys/stat.h>
#include "esp_vfs_fat.h"
#include "sdmmc_cmd.h"
#include "driver/sdmmc_host.h"
#include <driver/i2s.h>
static const char *TAG = "example";
#define MOUNT_POINT "/sdcard"
#define SAMP_RATE (325000 * 2)
#define BITS_PER_SAMPLE 16
#define BLCK 20800000
//#define SAMP_RATE 44100
//#define BITS_PER_SAMPLE 32
#define DMA_CHUNK_SIZE 1024
#define BUFFER_SIZE 32768
//#define BUFFER_SIZE DMA_CHUNK_SIZE
uint8_t buffer[BUFFER_SIZE];
void configure_port(i2s_port_t port) {
//Set up I2S
i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_SLAVE | I2S_MODE_RX),
.sample_rate = SAMP_RATE,
.bits_per_sample = BITS_PER_SAMPLE,
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, // Interrupt level 1, default 0
.dma_buf_count = 32,
.dma_buf_len = DMA_CHUNK_SIZE,
.use_apll = true,
.tx_desc_auto_clear = false,
.fixed_mclk = BLCK,
.mclk_multiple = I2S_MCLK_MULTIPLE_DEFAULT,
//.bits_per_chan = 0
};
i2s_driver_install(port, &i2s_config, 0, NULL);
//Set up pins
i2s_pin_config_t pin_config = {
.bck_io_num = 18,
.ws_io_num = 5,
.data_out_num = I2S_PIN_NO_CHANGE,
.data_in_num = 23
};
i2s_set_pin(port, &pin_config);
}
void print_status(const char* text, int64_t start, int total) {
//int target = 16*1024*1024;//(SAMP_RATE * (BITS_PER_SAMPLE / 8)) * 10;
int target = 2600000 * 10;//(SAMP_RATE * (BITS_PER_SAMPLE / 8)) * 10;
int64_t end = esp_timer_get_time();
double speed = target / ((end - start) / 1000000.0);
double target_speed = 2600000;
ESP_LOGI(TAG, "%s (written %i bytes; %f bytes/sec, %f%% of target)", text, total, (float)speed, (float)((speed / target_speed) * 100.0));
}
void app_main(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 = BUFFER_SIZE
};
sdmmc_card_t *card;
const char mount_point[] = MOUNT_POINT;
ESP_LOGI(TAG, "Initializing SD card");
// Use settings defined above to initialize SD card and mount FAT filesystem.
// Note: esp_vfs_fat_sdmmc/sdspi_mount is all-in-one convenience functions.
// Please check its source code and implement error recovery when developing
// production applications.
ESP_LOGI(TAG, "Using SDMMC peripheral");
sdmmc_host_t host = SDMMC_HOST_DEFAULT();
host.max_freq_khz = SDMMC_FREQ_HIGHSPEED;
// 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.
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
// To use 1-line SD mode, change this to 1:
slot_config.width = 4;
// Enable internal pullups on enabled pins. The internal pullups
// are insufficient however, please make sure 10k external pullups are
// connected on the bus. This is for debug / example purpose only.
slot_config.flags |= SDMMC_SLOT_FLAG_INTERNAL_PULLUP;
ESP_LOGI(TAG, "Mounting filesystem");
ret = esp_vfs_fat_sdmmc_mount(mount_point, &host, &slot_config, &mount_config, &card);
if (ret != ESP_OK) {
if (ret == ESP_FAIL) {
ESP_LOGE(TAG, "Failed to mount filesystem. "
"If you want the card to be formatted, set the EXAMPLE_FORMAT_IF_MOUNT_FAILED menuconfig option.");
vTaskDelay(1000 / portTICK_PERIOD_MS);
esp_restart();
} 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));
vTaskDelay(1000 / portTICK_PERIOD_MS);
esp_restart();
}
return;
}
ESP_LOGI(TAG, "Filesystem mounted");
// Card has been initialized, print its properties
sdmmc_card_print_info(stdout, card);
//Set up ports
configure_port(I2S_NUM_0);
//Open output file
FILE* output = fopen("/sdcard/out.bin", "wb");
if (output == 0) {
ESP_LOGE(TAG, "Failed to open output file.");
vTaskDelay(1000 / portTICK_PERIOD_MS);
esp_restart();
}
//Enter read loop
size_t read;
int total = 0;
int target = 2600000 * 10;
int64_t start = esp_timer_get_time();
int64_t last_log = start;
while (total < target) {
//Read
i2s_read(I2S_NUM_0, buffer, sizeof(buffer), &read, /*portMAX_DELAY*/100);
//read = sizeof(buffer);
if (read == 0)
printf("WARN: Read nothing!\n");
//Write
fwrite(buffer, 1, read, output);
//Log once a second
if (esp_timer_get_time() - last_log > 1000000) {
print_status("READING IN PROGRESS...", start, total);
last_log = esp_timer_get_time();
}
//Set
total += read;
}
print_status("DONE READING.", start, total);
fclose(output);
// All done, unmount partition and disable SDMMC peripheral
esp_vfs_fat_sdcard_unmount(mount_point, card);
ESP_LOGI(TAG, "Card unmounted");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment