Skip to content

Instantly share code, notes, and snippets.

@Roman-Port
Created April 21, 2022 22:25
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/ad1e30d6e3578738f8c7891152b94ed2 to your computer and use it in GitHub Desktop.
Save Roman-Port/ad1e30d6e3578738f8c7891152b94ed2 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";
// General
#define MOUNT_POINT "/sdcard"
#define MICROSECONDS_PER_SECOND 1000000
#define SECTOR_COUNT 64
//#define IQ_MODE
#ifdef IQ_MODE
/* IQ Baseband Mode (ground=red, 23=orange, 18=green, 5=blue) */
#define SAMPLE_RATE (325000 * 2)
#define BITS_PER_SAMPLE 16
#define FIXED_MCLK 20800000
#define COMM_FMT I2S_COMM_FORMAT_STAND_I2S
#define USE_APLL true
/* END IQ Baseband Mode */
#else
/* HD Mode (ground=blue, 23=orange, 18=yellow, 5=green) */
#define SAMPLE_RATE 44100
#define BITS_PER_SAMPLE 32
#define FIXED_MCLK 0
#define COMM_FMT I2S_COMM_FORMAT_STAND_I2S
#define USE_APLL false
/* END HD Mode */
#endif
int64_t configure_port(i2s_port_t port, int dmaChunkSize) {
//Set up I2S
i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_SLAVE | I2S_MODE_RX),
.sample_rate = SAMPLE_RATE,
.bits_per_sample = BITS_PER_SAMPLE,
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
.communication_format = COMM_FMT,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, // Interrupt level 1, default 0
.dma_buf_count = 32,
.dma_buf_len = dmaChunkSize,
.use_apll = USE_APLL,
.tx_desc_auto_clear = false,
.fixed_mclk = FIXED_MCLK,
.mclk_multiple = I2S_MCLK_MULTIPLE_DEFAULT
};
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);
//Calculate data rate
return SAMPLE_RATE * (BITS_PER_SAMPLE / 8) * 2;
}
void app_main(void)
{
//Initialize SD card driver
if (sdmmc_host_init() != ESP_OK) {
printf("Failed to initialize SD card driver.\n");
return;
}
//Initialize slot
sdmmc_slot_config_t slot = SDMMC_SLOT_CONFIG_DEFAULT();
slot.width = 4;
slot.flags |= SDMMC_SLOT_FLAG_INTERNAL_PULLUP;
if (sdmmc_host_init_slot(1, &slot) != ESP_OK) {
printf("Failed to initialize SD card slot.\n");
return;
}
//Open card
printf("Opening SD card...\n");
sdmmc_host_t host = SDMMC_HOST_DEFAULT();
host.max_freq_khz = SDMMC_FREQ_HIGHSPEED;
sdmmc_card_t card;
if (sdmmc_card_init(&host, &card) != ESP_OK) {
printf("Failed to open SD card! Rebooting...\n");
vTaskDelay(1000 / portTICK_PERIOD_MS);
esp_restart();
}
//Get info
sdmmc_card_print_info(stdout, &card);
printf("Sector size: %i\n", card.csd.sector_size);
//Set up ports
int64_t targetByteRate = configure_port(I2S_NUM_0, card.csd.sector_size);
//Allocate sector buffer
size_t bufferSize = SECTOR_COUNT * card.csd.sector_size;
void* buffer = malloc(bufferSize);
if (buffer == 0) {
printf("Failed to allocate buffer!\n");
return;
}
//Enter loop
size_t read;
int sector = 0;
int64_t start = esp_timer_get_time();
int64_t end = esp_timer_get_time();
while (true) {
//Read
i2s_read(I2S_NUM_0, buffer, bufferSize, &read, 300);//portMAX_DELAY
if (read == 0)
printf("WARN: No data is being read from I2S!\n");
//Write
end = esp_timer_get_time();
if (sdmmc_write_sectors(&card, buffer, sector, SECTOR_COUNT) != ESP_OK) {
printf("Failed to write sectors to SD card! Aborting...\n");
break;
}
//Advance
sector += SECTOR_COUNT;
}
//Print info
int64_t written = sector * card.csd.sector_size;
double speed = written / ((end - start) / 1000000.0);
ESP_LOGI(TAG, "FINISHED WRITING. Wrote %i sectors (%lli bytes) at %f bytes/sec (%f%% of target)", sector, written, (float)speed, (float)((speed / targetByteRate) * 100.0));
}
@Roman-Port
Copy link
Author

(ps, there's a memory leak since I forgot to free the buffer)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment