Avanxe 7 – Aplicación 7: Reproductor de audio con MicroSD

En esta aplicación se mostrará cómo leer un archivo .wav de una memoria MicroSD  para que Avanxe 7 funcione como un reproductor de audio.

Para facilitar la lectura de datos de la MicroSD se utiliza el ESP32 integrado en Avanxe 7, se encargará de inicializar y configurar la memoria así como generar la interfaz SPI.

IMPORTANTE: Leer la documentación oficial de ESPRESSIF y seguir los pasos para poder programar el ESP32 en Eclipse.

Se utiliza el protocolo RS232 para la transferencia de datos que lee el ESP32 de la memoria microSD, el protocolo cuenta con las siguientes características:

  • 3 Megabaudios
  • 1 bit de inicio
  • 8 bits de datos
  • 1 bit de paro
  • Sin paridad

Para la microSD se utiliza el protocolo serial SPI, el código en C se encarga de obtener los parámetros que requiere la memoria y configura al ESP32 de manera automática. La conexión es la siguiente

El proyecto se divide en 2 partes:

  1. Código en VHDL que se encarga del control del DAC y adquisición de datos.
  2. Código en Eclipse para el ESP32 utilizando el framework oficial de Espressif ESP-IDF.

Código en VHDL

El código sigue la siguiente estructura:

Funciona como un puente entre el ESP32 y el DAC, utiliza un buffer de doble puerto en donde se almacenan temporalmente los datos del archivo WAV. También sincroniza los tiempos de muestreo que indica el formato de audio.  Como el periodo de muestreo es mucho menor que el tiempo de adquisición de datos, el buffer se puede llenar de datos y esperar a que el DAC termine de leer todos los datos.

Código en Eclipse.

El framework ESP-IDF ofrece librerías y ejemplos sobre cómo leer o escribir en la microSD. Se utilizó el código de ejemplo creado por Espressif y se le añadió la comunicación UART para transferir los datos al FPGA.

IMPORTANTE: El archivo de audio debe ser formato WAV a un canal, frecuencia de muestro de 22050 y con una resolución de 8 bits para que el sistema funcione correctamente.

El código en C inicializa la memoria SD y después obtiene toda la información del archivo WAV que se puede observar en la terminal de Ecplise.

//Capturan los datos
        char data[4];
        char data2[2];
        long int val;
        //ChunkID
    //fgets(data, sizeof(data), f2);
    fread(data,sizeof(data),1,f2);
    ESP_LOGI(TAG, "ChunkID: '%s'",data);
    //ChunkSize
    //fgets(data, sizeof(data), f2);
    fread(data,sizeof(data),1,f2);
    val = ((data[3])<<24)+ ((data[2])<<16)+ ((data[1])<<8) + (data[0]);
    ESP_LOGI(TAG, "Chunk Size: '%li'",val);
    //Format
    fread(data,sizeof(data),1,f2);
    ESP_LOGI(TAG, "Format: '%s'",data);
    //Subchunk1ID
    fread(data,sizeof(data),1,f2);
    ESP_LOGI(TAG, "Subchunk1ID: '%s'",data);
    //Subchunk1Size
    fread(data,sizeof(data),1,f2);
    val = ((data[3])<<24)+ ((data[2])<<16)+ ((data[1])<<8) + (data[0]);
    ESP_LOGI(TAG, "Subchunk1Size Size: '%li'",val);
    //Audioformat
    fread(data2,sizeof(data2),1,f2);
    val = ((data2[1])<<8) + (data2[0]);
    ESP_LOGI(TAG, "Audioformat: '%li'",val);
    //NumChannels
    fread(data2,sizeof(data2),1,f2);
    val = ((data2[1])<<8) + (data2[0]);
    ESP_LOGI(TAG, "NumChannels: '%li'",val);
    //SampleRate
    fread(data,sizeof(data),1,f2);
    val = ((data[3])<<24)+ ((data[2])<<16)+ ((data[1])<<8) + (data[0]);
    ESP_LOGI(TAG, "SampleRate: '%li'",val);
    //ByteRate
    fread(data,sizeof(data),1,f2);
    val = ((data[3])<<24)+ ((data[2])<<16)+ ((data[1])<<8) + (data[0]);
    ESP_LOGI(TAG, "ByteRate: '%li'",val);
    //BlockAlign
    fread(data2,sizeof(data2),1,f2);
    val = ((data2[1])<<8) + (data2[0]);
    ESP_LOGI(TAG, "BlockAlign: '%li'",val);
    //BitsPerSample
    fread(data2,sizeof(data2),1,f2);
    val = ((data2[1])<<8) + (data2[0]);
    ESP_LOGI(TAG, "BitsPerSample: '%li'",val);
    //Subchunk2ID
    fread(data,sizeof(data),1,f2);
    ESP_LOGI(TAG, "Subchunk2ID: '%s'",data);
    //Subchunk2Size
    fread(data,sizeof(data),1,f2);
    val = ((data[3])<<24)+ ((data[2])<<16)+ ((data[1])<<8) + (data[0]);
    ESP_LOGI(TAG, "Subchunk2Size: '%li'",val);
Menú