/main/sd.c
#include <ctype.h>
#include <dirent.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "diskio_impl.h"
#include "diskio_sdmmc.h"
#include "esp_vfs_fat.h"
#include "sdmmc_cmd.h"
#include "gfx.h"
#include "keyboard.h"
#include "sd.h"
#define TAG "sd"
sdmmc_host_t host = SDSPI_HOST_DEFAULT();
const char mount_point[] = "/sd";
FATFS* fs;
bool sd_card_detect() {
return !(bool)gpio_get_level(GPIO_NUM_13);
}
int sd_init() {
esp_err_t ret;
ESP_LOGI(TAG, "Initializing SPI bus");
spi_bus_config_t bus_cfg = {
.mosi_io_num = 23,
.miso_io_num = 19,
.sclk_io_num = 18,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = 4000,
};
ret = spi_bus_initialize(host.slot, &bus_cfg, SPI_DMA_CH_AUTO);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to initialize bus: %s", esp_err_to_name(ret));
return 0;
}
sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT();
slot_config.gpio_cs = 5;
slot_config.host_id = host.slot;
ESP_LOGI(TAG, "Initializing SDSPI device");
sdspi_dev_handle_t sdspi;
ret = sdspi_host_init_device(&slot_config, &sdspi);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to init SDSPI device: %d", ret);
return 0;
}
ret = sdspi_host_set_card_clk(sdspi, 20000);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to set SPI card speed: %d", ret);
return 0;
}
return 1;
}
FATFS * sd_card_mount() {
esp_err_t ret;
ESP_LOGI(TAG, "Initializing SD card");
sdmmc_card_t *card = (sdmmc_card_t *) malloc(sizeof(sdmmc_card_t));
if (card == NULL) {
ESP_LOGE(TAG, "Could not allocate card struct");
}
host.max_freq_khz = 1600;
ret = sdmmc_card_init(&host, card);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to init SD card: %s", esp_err_to_name(ret));
return NULL;
}
sdmmc_card_print_info(stdout, card);
ESP_LOGI(TAG, "Mounting filesystem");
BYTE pdrv = 0;
ff_diskio_register_sdmmc(pdrv, card);
FATFS *fs = NULL;
ret = esp_vfs_fat_register(mount_point, "0:", 5, &fs);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to register VFS: %d", ret);
return NULL;
}
FRESULT fret = f_mount(fs, "0:", 1);
if (fret != FR_OK) {
ESP_LOGE(TAG, "Failed to mount FATFS: %d", fret);
}
ESP_LOGI(TAG, "Filesystem mounted on %s", mount_point);
return fs;
}
void sd_card_unmount() {
esp_err_t ret;
f_unmount("0:");
ret = esp_vfs_fat_unregister_path(mount_point);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "can't unmount: %s not mounted", mount_point);
return;
}
ESP_LOGI(TAG, "%s unmounted", mount_point);
ff_diskio_register(0, NULL);
ESP_LOGI(TAG, "disk driver freed");
}
FATFS* sd_get() {
if (!sd_card_detect()) {
sd_card_unmount();
fs = NULL;
return NULL;
}
if (fs == NULL) {
fs = sd_card_mount();
}
return fs;
}
bool sd_ready() {
return sd_card_detect() && fs != NULL;
}
void test_sd() {
gfx_set_enabled(false);
char buf[40];
key_event_t ke;
int cs_state = 1;
FATFS *fs = NULL;
while (ke = key_get_event(0), !(ke.type == KEY_PRESSED && ke.code == KEY_BAND)) {
int new_cs_state = gpio_get_level(GPIO_NUM_13);
if (!new_cs_state && cs_state) {
// card inserted
fs = sd_card_mount();
if (fs == NULL) {
ESP_LOGE(TAG, "Could not initialize SD");
cs_state = new_cs_state;
continue;
}
DIR *d = opendir("/sd");
struct dirent *e;
while ((e = readdir(d)) != NULL) {
printf("%02x %s\n", e->d_type, e->d_name);
}
closedir(d);
} else if (new_cs_state && !cs_state) {
sd_card_unmount();
fs = NULL;
// card removed
}
cs_state = new_cs_state;
u8g2_ClearBuffer(&u8g2);
sprintf(buf, "CS: %c", cs_state ? 'H' : 'L');
u8g2_DrawStr(&u8g2, 0, 6, buf);
sprintf(buf, "FS: %p", fs);
for (int i = 0; i < strlen(buf); i++) {
buf[i] = toupper(buf[i]);
}
u8g2_DrawStr(&u8g2, 0, 12, buf);
u8g2_SendBuffer(&u8g2);
vTaskDelay(100 / portTICK_PERIOD_MS);
}
gfx_set_enabled(true);
}