#include <stdio.h>
#include <string.h>
#include <sys/unistd.h>
#include <sys/stat.h>
#include "esp_vfs_fat.h"
#include "sdmmc_cmd.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/uart.h"
#define EXAMPLE_MAX_CHAR_SIZE 512
#define MOUNT_POINT "/sdcard"
#define PIN_NUM_MISO 19
#define PIN_NUM_MOSI 23
#define PIN_NUM_CLK 18
#define PIN_NUM_CS 5
#define UART_TX_PIN 1
#define UART_RX_PIN 3
static const char *TAG = "sd_card";
static char text[EXAMPLE_MAX_CHAR_SIZE] = {0};
static int cursor_pos = 0;
static char nombre_archivo[EXAMPLE_MAX_CHAR_SIZE] = "default.txt";
static esp_err_t s_example_read_file(const char *path) // leer
{
ESP_LOGI(TAG, "Abriendo archivo %s", path);
FILE *f = fopen(path, "r");
if (f == NULL)
{
ESP_LOGE(TAG, "Fallo abrir el archivo para lectura");
return ESP_FAIL;
}
memset(text, 0, EXAMPLE_MAX_CHAR_SIZE); // Limpia el buffer de texto
fread(text, 1, EXAMPLE_MAX_CHAR_SIZE - 1, f); // Lee el contenido del archivo en el buffer de texto
fclose(f);
cursor_pos = strlen(text);
ESP_LOGI(TAG, "Contenido del archivo: '%s'", text);
return ESP_OK;
}
static esp_err_t s_example_write_file(const char *path, const char *data) // Escribir
{
ESP_LOGI(TAG, "Abriendo archivo %s", path);
FILE *f = fopen(path, "w");
if (f == NULL)
{
ESP_LOGE(TAG, "Fallo abrir el archivo para escritura");
return ESP_FAIL;
}
fprintf(f, "%s", data);
fclose(f);
ESP_LOGI(TAG, "Archivo escrito");
return ESP_OK;
}
void app_main(void)
{
esp_err_t ret;
sdmmc_card_t *card;
ESP_LOGI(TAG, "Inicializando SD card");
ESP_LOGI(TAG, "Usando periférico SPI");
sdmmc_host_t host = SDSPI_HOST_DEFAULT();
host.max_freq_khz = 5000;
spi_bus_config_t bus_cfg = {
.mosi_io_num = PIN_NUM_MOSI,
.miso_io_num = PIN_NUM_MISO,
.sclk_io_num = PIN_NUM_CLK,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = 4000,
};
ret = spi_bus_initialize(host.slot, &bus_cfg, SDSPI_DEFAULT_DMA);
if (ret != ESP_OK)
{
ESP_LOGE(TAG, "Fallo al inicializar el bus.");
return;
}
sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT();
slot_config.gpio_cs = PIN_NUM_CS;
slot_config.host_id = host.slot;
ESP_LOGI(TAG, "Montando el filesystem");
ret = esp_vfs_fat_sdspi_mount(MOUNT_POINT, &host, &slot_config, &(esp_vfs_fat_sdmmc_mount_config_t){
.format_if_mount_failed = true,
.max_files = 5,
.allocation_unit_size = 16 * 1024
},
&card);
if (ret != ESP_OK)
{
ESP_LOGE(TAG, "Fallo al montar el filesystem");
return;
}
ESP_LOGI(TAG, "Montando el filesystem");
// UART
uart_config_t uart_config = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_APB,
};
uart_driver_install(UART_NUM_0, 256, 0, 0, NULL, 0);
uart_param_config(UART_NUM_0, &uart_config);
uart_set_pin(UART_NUM_0, UART_TX_PIN, UART_RX_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
char cmd = 0; // variable para almacenar el comando recibido por UART
while (1)
{
if (uart_read_bytes(UART_NUM_0, &cmd, 1, 1000 / portTICK_PERIOD_MS) > 0) // espera y lee un byte del UART0 con un tiempo de espera de 1 segundo
{
switch (cmd) // comando recibido
{
case 0x1B: // ESC
ESP_LOGI(TAG, "Modo comando");
while (1)
{
if (uart_read_bytes(UART_NUM_0, &cmd, 1, 1000 / portTICK_PERIOD_MS) > 0) // Espera y lee un byte del UART0 con un tiempo de espera de 1 segundo
{
switch (cmd)
{
case 'u': // Comando 'u' para recibir texto por UART
ESP_LOGI(TAG, "Recibiendo texto");
memset(text, 0, EXAMPLE_MAX_CHAR_SIZE); // Limpia el buffer de texto
cursor_pos = 0; // posicion del cursor
while (1)
{
if (uart_read_bytes(UART_NUM_0, (uint8_t *)text + cursor_pos, 1, 1000 / portTICK_PERIOD_MS) > 0)
{
if (text[cursor_pos] == 0x1B) // Verifica si recibio la tecla ESC
{
text[cursor_pos] = '\0'; // Agrega el caracter nulo al final del texto
uart_write_bytes(UART_NUM_0, "\r\n", 2); // nueva linea
ESP_LOGI(TAG, "Texto recibido: '%s'", text);
break;
}
cursor_pos++; // se incrementa posicion del cursor
uart_write_bytes(UART_NUM_0, text + cursor_pos - 1, 1); // envia el ultimo caracter recibido de vuelta al UART0
}
}
break;
case 'o': // Comando 'o' para abrir un archivo
ESP_LOGI(TAG, "Abra un archivo:");
memset(nombre_archivo, 0, EXAMPLE_MAX_CHAR_SIZE);
cursor_pos = 0;
while (1)
{
if (uart_read_bytes(UART_NUM_0, (uint8_t *)nombre_archivo + cursor_pos, 1, 1000 / portTICK_PERIOD_MS) > 0)
{
if (nombre_archivo[cursor_pos] == 0x1B)
{
nombre_archivo[cursor_pos] = '\0';
uart_write_bytes(UART_NUM_0, "\r\n", 2);
ESP_LOGI(TAG, "Abriendo archivo: %s", nombre_archivo);
char file_path[EXAMPLE_MAX_CHAR_SIZE];
strncpy(file_path, MOUNT_POINT, sizeof(file_path) - 1);
strncat(file_path, "/", sizeof(file_path) - strlen(file_path) - 1);
strncat(file_path, nombre_archivo, sizeof(file_path) - strlen(file_path) - 1);
s_example_read_file(file_path);
break;
}
cursor_pos++;
uart_write_bytes(UART_NUM_0, nombre_archivo + cursor_pos - 1, 1); // envia el ultimo caracter recibido de vuelta al UART0
}
}
break;
case 'e': // Comando 'e' para entrar en el modo de edicin
ESP_LOGI(TAG, "Entrando al modo edicion.");
while (1)
{
uint8_t input_buffer[32];
int num_bytes = uart_read_bytes(UART_NUM_0, input_buffer, sizeof(input_buffer), 100 / portTICK_PERIOD_MS);
if (num_bytes > 0) // Verifica si se recibieron bytes
{
for (int i = 0; i < num_bytes; i++)
{
uint8_t c = input_buffer[i]; // Obtiene el caracter actual
if (c == 0x1B) // verifica si recibio ESC
{
if (i + 2 < num_bytes && input_buffer[i + 1] == 0x5B) // verifica si recibio '['
{
switch (input_buffer[i + 2])
{
case 0x44: // Flecha izquierda
if (cursor_pos > 0) // si el cursor no esta al inicio del texto
{
cursor_pos--; // mueve el cursor hacia la izquierda
}
i += 2; // salta los caracteres de la secuencia de la flecha
break;
case 0x43: // Flecha derecha
if (cursor_pos < strlen(text)) // verifica si el cursor no esta al final del texto
{
cursor_pos++; // mueve el cursor hacia la derecha
}
i += 2; // Salta los caracteres de la secuencia de la flecha
break;
default:
uart_write_bytes(UART_NUM_0, "\r\n", 2); // nueva linea
ESP_LOGI(TAG, "Saliendo del modo edicion...");
goto salir_edicion; // Salta a la etiqueta
}
}
else
{
uart_write_bytes(UART_NUM_0, "\r\n", 2); // nueva linea
ESP_LOGI(TAG, "Saliendo del modo edicion...");
goto salir_edicion;
}
}
else if (c == 0x08) // Verifica si recibe Backspace
{
if (cursor_pos > 0) // Si el cursor no esta al inicio del texto
{
memmove(text + cursor_pos - 1, text + cursor_pos, strlen(text + cursor_pos) + 1); // Mueve los caracteres a la izquierda del cursor hacia la izquierda
cursor_pos--; // Mueve el cursor hacia la izquierda
}
}
else
{
if (cursor_pos < EXAMPLE_MAX_CHAR_SIZE - 1) // Si el cursor no esta al final del buffer de texto
{
memmove(text + cursor_pos + 1, text + cursor_pos, strlen(text + cursor_pos) + 1); // Mueve los caracteres a la derecha del cursor hacia la derecha
text[cursor_pos] = c; // Inserta el caracter en la posicion del cursor
cursor_pos++; // Mueve el cursor hacia la derecha
}
}
}
uart_write_bytes(UART_NUM_0, "\r\x1B[0K", 5);
uart_write_bytes(UART_NUM_0, text, strlen(text));
if (cursor_pos < strlen(text))
{
char cursor_move[16];
snprintf(cursor_move, sizeof(cursor_move), "\x1B[%dD", (int)strlen(text) - cursor_pos);
uart_write_bytes(UART_NUM_0, cursor_move, strlen(cursor_move));
}
}
}
salir_edicion:
break;
case 'n': // Comando 'n' para ingresar el nombre del archivo
uart_write_bytes(UART_NUM_0, "\r\n", 2); // nueva linea
ESP_LOGI(TAG, "Ingresa el nombre del archivo");
memset(nombre_archivo, 0, EXAMPLE_MAX_CHAR_SIZE); // Limpia el bufer de nombre de archivo
cursor_pos = 0;
while (1)
{
if (uart_read_bytes(UART_NUM_0, (uint8_t *)nombre_archivo + cursor_pos, 1, 1000 / portTICK_PERIOD_MS) > 0)
{
if (nombre_archivo[cursor_pos] == 0x1B) // Si recibio la tecla ESC
{
nombre_archivo[cursor_pos] = '\0';
uart_write_bytes(UART_NUM_0, "\r\n", 2); // nueva linea
ESP_LOGI(TAG, "Nombre del archivo: %s", nombre_archivo);
break;
}
cursor_pos++;
uart_write_bytes(UART_NUM_0, nombre_archivo + cursor_pos - 1, 1);
}
}
break;
case 's': // Comando 's' para guardar el archivo
ESP_LOGI(TAG, "Guardando el archivo");
char file_path[EXAMPLE_MAX_CHAR_SIZE]; // Buffer para almacenar la ruta completa del archivo
if (strlen(nombre_archivo) == 0) // si no se ingresa nombre del archivo crea 'default.txt' por defecto
{
strncpy(file_path, MOUNT_POINT, sizeof(file_path) - 1);
strncat(file_path, "/", sizeof(file_path) - strlen(file_path) - 1);
strncat(file_path, "default.txt", sizeof(file_path) - strlen(file_path) - 1);
}
else
{
strncpy(file_path, MOUNT_POINT, sizeof(file_path) - 1);
strncat(file_path, "/", sizeof(file_path) - strlen(file_path) - 1);
strncat(file_path, nombre_archivo, sizeof(file_path) - strlen(file_path) - 1);
}
uart_write_bytes(UART_NUM_0, "\r\n", 2); // nueva linea
s_example_write_file(file_path, text); // Llama a la funcion para escribir el nombre del archivo
break;
default:
ESP_LOGI(TAG, "Comando desconocido.");
break;
}
}
}
break;
default:
ESP_LOGI(TAG, "Entrada desconocida.");
break;
}
}
}
}