Last active
April 20, 2022 20:53
-
-
Save Roman-Port/4ac24ee780f6836a9ec17c1f869c1c7f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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