Skip to content

File CopyingWavs.cpp

File List > CopyingWavs > CopyingWavs.cpp

Go to the documentation of this file

Source Code

// WAV Copying
// Example of how to copy WAV file over to QSPI flash
//
// Setup:
// * Insert an SD card into a connected SDMMC receptacle
//
#include "daisy_seed.h"

using namespace daisy;

DaisySeed hw;

// These classes are necessary for interacting with FatFS
SdmmcHandler sd;
FatFSInterface fsi;
FIL file;

// Powers of two are best for this data buffer to keep QSPI
// writes aligned to the sectors.
#define DATA_BUFFER_LEN 4096
uint8_t data_buffer[DATA_BUFFER_LEN];

// Change this to the file you'd like to copy
#define FILE_NAME "my_wav.wav"

// You can find the information on the QSPI's length
// in the linker scripts, among other places
#define QSPI_LEN     0x00800000U

#define SECTOR_SIZE  65536

void copy_wav(const char* filename);

int main(void)
{
    // Initialize the Daisy Seed
    hw.Init();

    // Run the copy routine
    copy_wav(FILE_NAME);

    // The LED will illuminate when the copying is complete. For
    // large files, this can take some time.
    hw.SetLed(true);

    while(1);
}

void copy_wav(const char* filename)
{
    // Initialize the SDMMC interface and FatFS drivers
    SdmmcHandler::Config sd_cfg;
    sd_cfg.Defaults();
    sd.Init(sd_cfg);
    fsi.Init(FatFSInterface::Config::MEDIA_SD);

    if (f_mount(&fsi.GetSDFileSystem(), fsi.GetSDPath(), 1) != FR_OK)
    {
        // If some error is encountered in mounting the card, then simply return.
        return;
    }

    if (f_open(&file, filename, FA_OPEN_EXISTING | FA_READ) != FR_OK)
    {
        // If some error is encountered in opening the file, then simply return.
        f_close(&file);
        return;
    }

    UINT data_read;
    WAV_FormatTypeDef wav_header;

    // This will populate the wav_header struct with all the data we 
    // need to parse the wav file. Currently, the code doesn't actually use this header,
    // but you could write code that converts from the
    // several possible WAV storage types to int16_t or float for consistency.
    // It seems easier to simply ensure your WAV files are all in the same format, though.

    // You could also write this header along with the audio data if you'd like to
    // parse the wav file in your actual project.

    f_read(&file, &wav_header, sizeof(wav_header), &data_read);

    // This helps us keep track of the QSPI address to write to
    // between file data chunks. You can set its initial value to
    // whatever you want -- you'll just need to remember where that
    // is so your target application can load it from QSPI.
    uint32_t current_qspi_offset = 0;

    do
    {
        // This avoids attempted writes beyond the QSPI's address space
        if (current_qspi_offset >= QSPI_LEN)
            break;

        // The QSPI chip must be erased before any writes can be made,
        // and it can only be erased in certain sizes (4K, 32K, 64K, and full chip erase).
        // 64K is the fastest per byte without being too large, so that's what we'll use.
        if (current_qspi_offset % SECTOR_SIZE == 0)
        {
            hw.qspi.Erase(current_qspi_offset, current_qspi_offset + SECTOR_SIZE);
        }
        f_read(&file, data_buffer, DATA_BUFFER_LEN, &data_read);

        hw.qspi.Write(current_qspi_offset, data_read, data_buffer);
        current_qspi_offset += data_read;
    } while (data_read == DATA_BUFFER_LEN);

    f_close(&file);
}