[Wiki]Everything there is to know about SD Card access

Troubleshooting

Something not working? Make sure your Pokitto’s battery is charged. Some cards can be picky about voltage.
Still not working? Try another card. FAT is brittle.

Available APIs

There are three ways to access the SD card from your code. Each has its pros and cons:

- PokittoDisk

Based on PetitFatFs (PFFS).
Pros: The smallest of the three libs.
Cons: Limited to one file at a time, 8-char filenames only.

#include <Pokitto.h>
void readExample(char *buffer, int length){
  pokInitSD();
  if(fileOpen("filename", FILE_MODE_READONLY) == 0)
    fileReadBytes(buffer, length);
  fileClose();
}

- SDFileSystem (SDFS)

Based on FatFs.
Pros: The most feature-complete.
Cons: The slowest, largest of the three. API is problematic. Not available in simulator.
Notes:

  • Use of the C fopen function results in a memory leak. Use the SDFS directly, like in the example below.
#include <SDFileSystem.h>
...
void readExample(char *buffer, int amount){
  auto sdfs = new SDFileSystem(P0_9, P0_8, P0_6, P0_7, "sd", NC, SDFileSystem::SWITCH_NONE, 24000000 );
  auto file = sdfs->open("filename", O_RDONLY);
  if(file){
    file->read(buffer, amount);
    file->close();
  }
}

- File

Also based on FatFs.
Pros: Faster than the other two. Simple API. Works in simulator, hardware and emulator.
Cons: Still under development, but already available in PokittoLib.

#include <File>
void readExample(char *buffer, int amount){
  File file;
  if(file.openRO("filename"))
    file.read(buffer, amount);
}

You can use the File API together with SDFS by using the following in your My_settings.h:
#define PROJ_SDFS_STREAMING
It will initialize SDFS automatically, just create a File and use it. Always include File. You shouldn’t include the implementation headers (SIMFile/YAPFSFile/SDFSFile) directly.

7 Likes

Looks very good! Can I create a directory to the SD card using the File API?

What does this mean? Why there is 2 different “File” APIs: File and SDFSFile?

Not yet. mkdir was disabled to save space. I plan to make this configurable using a My_settings flag.

There is one API with multiple implementations. Generally, you just include File and it will pick the correct implementation depending on if you are in the simulator or if you are using SDFS already. This allows you to use the safer, leak-free, API even if some library in the same project wants to use SDFS directly.

(edit: updated the post for clarity)

1 Like

OK, I guess I need to use SDFileSystem until that has been implemented. Do you know if SDFileSystem works in the Simulator in FemtoIDE?

No, SDFS does not have Simulator support.

1 Like

ok, then I could use File for everything else and SDFileSystem just for mkdir. For the simulator I need to pre-create folders.
So File and SDFilesystem can be used in the same binary? Can I do the initialization normally like this:

`sdFs =new SDFileSystem( P0_9, P0_8, P0_6, P0_7, "sd", NC, SDFileSystem::SWITCH_NONE, 25000000 );`

Yes, but you need to have PROJ_SDFS_STREAMING in My_settings.h, otherwise the two libs are going to conflict with each other.

Yes, just make sure you do that before you try to use File, otherwise File is going to do that for you.

1 Like

Ok, good.

Btw. Is the File API still Simulator compatible if it is using SDFSFile? I suppose SDFSFile is a HW implementation, right?

Oh, right… no, that’s not going to work, SDFS is hardware-only. To create a directory in the Sim you’re going to have to call the native method directly.

Ok, better to use totally different API for the simulator then.

I am using the File approach but it doesn’t seem to work in the emulator. Should it?

My code:

#include "Pokitto.h"

#include <File>

void readExample(uint8_t *buffer, int amount){

  File file;
  printf("before buffer[0] %i\n", buffer[2]);   
  
  if(file.openRO("Smile.xxx"))
    file.read(buffer, amount);
  
  printf("after buffer[2] %i\n", buffer[2]);    

}

int main(){
    
    uint8_t bit[((16*16)/2)+2];
    
    using PC=Pokitto::Core;
    using PD=Pokitto::Display;
    PC::begin();
    PD::persistence = true;
    PD::invisiblecolor = 0;
    
    readExample(bit, 130);

    
    while( PC::isRunning() ){
        
        if( !PC::update(true) )  continue;

            PD::directBitmap(12, 12, bit, 4, 1);

    }
    
    return 0;
}

I am also trying to stream a 16 colour bitmap from the SD into an array for rendering with directBitmap(). How are people converting images (from png) to an appropriate file format?

1 Like

It should work, but it requires the file getting copied to a fake SD card image (.img file) and having that passed to the emulator. For my pinball testing I had to manually create one in linux and mount it as a loop device then pass it with the -I /path/to/sd.img to have it work. Problem is writing to the mounted folder doesn’t always seem to update the image file.

There might be something I’m doing slightly wrong with my setup. IIRC you should be able to right-click a file in FemtoIDE and check the box Copy to SD and it should do the rest for you, but I’m not sure on that approach as I haven’t done it.

file.openRO expects an absolute path to the file (including on the emulator, not sure about simulator), so it should be "/path/to/Smile.xxx for example my pinball table is stored in the pinball folder on the root of the sd so it would be /pinball/dragonrush.dat

I usually just write my own, since often I spend less time writing some quick 2-second tool then I spend finding the right tool then learning how to use it. I’m sure someone else can point you in the right direction there though.

1 Like

In the example I have give, the file is in the SD root folder.

1 Like

It should be enough to right-click on the file name, check Copy to SD then build.

Hmmm … that’s what I did.

Edit: A clean before building worked on that ! Silly me.

3 Likes

So … one gotcha that came out of my testing. The FemtoIDE interprets the file extension type before copying the file to the SD card. If it is an extension it does not recognise or one that it thinks should be text which breaks characters that are above 128 (hex 80).

In my example, I was using .xxx but had I used .bin (or any of these EEPROM, RAW, PNG, GIF, MAP, MP3, OGG, WAV, JPG, IMG, MOD, XM, PMF) the code works as expected.

7 Likes