electro-smith / libDaisy

Hardware Library for the Daisy Audio Platform
https://www.electro-smith.com/daisy
MIT License
312 stars 131 forks source link

f_open works but f_lseek and f_read does not #508

Closed MarianoDesivo closed 2 years ago

MarianoDesivo commented 2 years ago

I am trying to load wav data into SDRAM. So first I open a file with f_open() which returns 0 (no error)

But then if I try f_lseek() or f_read(), it returns 1 (FR_DISK_ERR) It prints:

Daisy is online↵ .===============↵ .Comenzando probarSDRAM.cpp↵ sdcart.init(): 0↵ fsi.Init: 0↵ f_mount: 0↵ abriendo: C4.wav↵ //no error with f_open() f_lseek error: 1 f_read no se puede abrir C4.wav error: 1 bytesRead: 0↵ .init audio↵ .fin del main() de probarSDRAM.cpp↵

If I don't use f_lseek(), bytesRead becomes 2 million instead of 0, still gives me error (and it left some hundred bytes to read). I thought it could be a problem of the SDRAM, but that does not explain why f_lseek() does not work. On the example WavPlayer.cpp you use f_lseek and f_read, and they seems to work

Here is my code:

#include <stdio.h>
#include <string.h>
#include "daisy_pod.h"

using namespace daisy;

DaisyPod       hw;
SdmmcHandler   sdcard;
FatFSInterface fsi;
WavPlayer      sampler;
int16_t DSY_SDRAM_BSS SDRAMsamples[1024 * 1024 * 32];

void AudioCallback(AudioHandle::InterleavingInputBuffer  in,
                   AudioHandle::InterleavingOutputBuffer out,
                   size_t                                size)
{

    for(size_t i = 0; i < size; i += 2)
    {
        static uint32_t indice = 0; //va de 0 a
        out[i]              = s162f(SDRAMsamples[indice]) * 0.5f;
        indice++;
        out[i + 1]          = s162f(SDRAMsamples[indice]) * 0.5f;
        indice++;
    }
}

int main(void)
{
    // Init hardware
    size_t blocksize = 4;
    hw.Init();
    hw.seed.StartLog(true);
    int error;
    System::Delay(3000);
    hw.seed.PrintLine("Comenzando probarSDRAM.cpp");
    System::Delay(3000);
    SdmmcHandler::Config sd_cfg;
    sd_cfg.Defaults();
    //hw.seed.PrintLine("sd_config.defaults(): %d", error);
    System::Delay(3000);
    SdmmcHandler::Result errorsdmmc = sdcard.Init(sd_cfg);
    System::Delay(3000);
    hw.seed.PrintLine("sdcart.init(): %d", errorsdmmc);
    System::Delay(3000);
    error = fsi.Init(FatFSInterface::Config::MEDIA_SD);
    System::Delay(3000);
    hw.seed.PrintLine("fsi.Init: %d", error);
    System::Delay(3000);
    error= f_mount(&fsi.GetSDFileSystem(), "/", 1);
    System::Delay(3000);
    hw.seed.PrintLine("f_mount: %d", error);

    sampler.Init(fsi.GetSDPath());
    sampler.SetLooping(true);

    FIL fil;
    uint8_t errorff;
    errorff = f_open( //devuelve zero si esta todo bien
        &fil,
        "C4.wav",
        (FA_OPEN_EXISTING | FA_READ));
    if(!errorff) //si abre bien, OpenByName() devuelve 0
        hw.seed.PrintLine("abriendo: %s", "C4.wav");
    else
        hw.seed.PrintLine("no se puede abrir %s  error: %d", "C4.wav", errorff);
    System::Delay(3000);
    //errorff = f_lseek(&fil, 44); //me salteo la metadata
    //if(!errorff) //si abre bien, OpenByName() devuelve 0
    //    hw.seed.PrintLine("f_lseek: %s", "C4.wav");
    //else
    //    hw.seed.PrintLine("f_lseek no se puede abrir %s  error: %d", "C4.wav", errorff);
    //System::Delay(3000);
    unsigned int bytesRead;
    do
    {
        errorff = f_read(
            &fil, SDRAMsamples, 1024 * 1024 * 4, &bytesRead); //lee de a 4Mb
        if(!errorff) //si abre bien, OpenByName() devuelve 0
              hw.seed.PrintLine("f_read: %s     bytesRead: %d", "C4.wav",bytesRead);
        else hw.seed.PrintLine(
            "f_read no se puede abrir %s  error: %d      bytesRead: %d", "C4.wav", errorff,bytesRead);
        System::Delay(3000);
    } while(bytesRead == 1024 * 1024 * 4);

    hw.seed.PrintLine("init audio");
        // Init Audio
    hw.SetAudioBlockSize(blocksize);
    hw.StartAudio(AudioCallback);
    hw.seed.PrintLine("fin del main() de probarSDRAM.cpp");

    for(;;)
    {
        // nothing
    }
}
stephenhensley commented 2 years ago

Hi @MarianoDesivo

The FIL object you're using has been created on the stack, and is therefore inaccessible to the SD peripheral.

It's interesting that the f_open call passes at all, but it could be that it doesn't actually start to read any data via the peripheral until the seek/read functions that actually perform diskio.

If you move the FIL fil object into global space it will be created in the default AXI SRAM sector instead of on the DTCMRAM used for the stack, and everything should work.

This is briefly touched on in the documentation for the FatFSInterface, but isn't specific about other FatFS objects, and should probably be mentioned in the SdmmcHandler, as well as having a dedicated guide in the docs. We'll work on getting some better documentation for this.

MarianoDesivo commented 2 years ago

Great! Thanks Stephen

it's a bit untidy (and some missing prints) but it read everything OK now:

chunksize:↵ WAVE:↵ . bytesread: 4↵ .f bytesread: 4. bytesread: 4. bytesread: 4. bytesread: 4↵ .Subchunk1Size 16 bytesRead: 4↵ .AudioFormat 1 bytesRead 2↵ .NumofChan 2 bytesRead 2↵ .Samplerate 48000 bytesRead 4↵ .byteRate 192000 bytesRead 4↵ .Block Aling 4 bytesRead 2↵ .Bit Depth 16 bytesRead 2↵ .d . . . bytesRead 4↵ .Subchunk2Size 2979536 bytesRead 4 ↵ .f_lseek: C4.wav↵ .f_read: C4.wav bytesRead: 2979536↵

Also I used this AudioCallBack to play the wav file from the SDRAM and it is working:

for(size_t i = 0; i < size; i += 2)
    {
        static uint16_t indice = 0; //only from 0 to 64k
        out[i]              = s162f(SDRAMsamples[indice]) * 0.5f;
        indice++;
        out[i + 1]          = s162f(SDRAMsamples[indice]) * 0.5f;
        indice++;
    }

Maybe I need to add a buffer instead of directly using the SDRAM in the AudioCallback

stephenhensley commented 2 years ago

@MarianoDesivo Glad to hear it's working!

I recommend using size_t or some other unsigned 32-bit int (e.g. uint32_t) for your index so you don't run into any issues when you try to read beyond the 2^16 sample.

Otherwise, you can read directly from the SDRAM in the audio callback. There are no problems doing that.

The performance of the 64MB SDRAM isn't quite as fast as the internal memory, but it is still quite fast.

I'm going to close the issue, but feel free to keep commenting if you have any other questions on the subject :)