Page 1 of 2

Any Petit FatFs example?

PostPosted: Tue Aug 11, 2015 12:01 pm
by mougino
I am making progress on my fighting fantasy engine, but in order to navigate through the encoded gamebook (a .LDV file on SD-Card) I need a FAT library. I saw that among the 2 available for Gamebuino only Petit FatFs allows to seek (i.e. place the pointer anywhere inside the file, which is what I need). Unfortunately my first attempts at opening the SD file have all failed. I have searched extensively on the net for any Arduino/PetitFatFs example but I didn't find any.

The simple code here:
Code: Select all
#include <petit_fatfs.h>
FATFS* fatfs;
[...]
void setup() {
  gb.begin();
  pf_mount(fatfs);
  int ldverr=pf_open("DF01.LDV");

always returns the error code FR_NOT_ENABLED meaning the SD-Card is not mounted.
This happens even when I am able to press C and install another game from bootloader (!) prooving of course that the SD is available...

I tried opening "/DF01.LDV" instead of "DF01.LDV" to no avail.

Any people here managed to make use of Petit FatFs lib to open a SD file, seek inside it, and read a buffer ?

Thanks in advance for any tip ;)
Nicolas

Re: Any Petit FatFs example?

PostPosted: Tue Aug 11, 2015 12:31 pm
by Valden
I didn't know for Petit FatFS, but at the moment, I'm using Fat16 (https://github.com/greiman/Fat16). The lib support seek, and it's very easy to use :

Code: Select all
#include <Fat16.h>

Fat16 file;

SdCard card;

void setup() {
card.init(); //Init the SD card
file.init(&card); //Init the file system
file.open("FILE.DAT", O_READ) //Open your file

file.seekSet(0xFF); //seek a position in a file
byte d = file.read(); //Read only one byte

byte data[8];
file.read(data,8); //Read a chunk of data

}

Re: Any Petit FatFs example?

PostPosted: Tue Aug 11, 2015 1:05 pm
by mougino
Thanks for reply Valden, I'll have a go at Fat16 then.

Nicolas

Re: Any Petit FatFs example?

PostPosted: Tue Aug 11, 2015 1:14 pm
by jonnection

Re: Any Petit FatFs example?

PostPosted: Tue Aug 11, 2015 1:40 pm
by mougino
Thanks jonnection! I'm studying your jvideo4.ino now.

Fat16 doesn't work for me, compilation fails. The lib seems to create a bunch of conflicts with "Robot_Control\ArduinoRobot.cpp" (I get "variable was not declared in this scope" with LCD_CS, DC_LCD, RST_LCD, MUXA, MUXB, MUXC, MUXD, MUX_IN, BUZZ, and Seriall)

Nicolas

Re: Any Petit FatFs example?

PostPosted: Tue Aug 11, 2015 2:09 pm
by mougino
Jonne, are you sure that the "jvideo4.ino" file at the site you referenced above is up-to-date?

It actually contains the following code:
Code: Select all
FRESULT res;       /* Petit FatFs function common result code */
[...]
  /* Mount the volume */
  //pf_mount(&fs);
  if (res) {
    Serial.println(F("File system mount failed"));
    //return;
  }

The code to mount the volume is commented, variable 'res' has no way to change... so I don't know how it can even work? :oops:

Re: Any Petit FatFs example?

PostPosted: Tue Aug 11, 2015 2:14 pm
by jonnection
Mougino: it works. I found out pf_mount is not needed ;-)

The "trick" with PetitFS is to make sure LCD_CS (spi enable line for LCD) and the SD_CS (enable for SD card) are released and reserved in proper order. You will find all that in jvideo4.ino. There is also an example how to FF and Rewind the playhead in the video (i.e. the seeking samples you need)

In my opinion PetitFS is the best option for Gamebuino projects because it does not require a buffer. All others (that I am aware of) require you to have a 512 B buffer to read a full sector at a time.

PetitFS has limitations (no new file creation, no file expansion) but if you can live with those I have found it to be extremely reliable.

Re: Any Petit FatFs example?

PostPosted: Tue Aug 11, 2015 2:19 pm
by jonnection
@ Mougino: in fact, I think there was some problem with pf_mount + it was unnecessary, so I left it out

Edit: I was looking at the code now... good grief. I really should comment what I am doing when I'm coding :lol: Not commenting is a bad bad habit.

Re: Any Petit FatFs example?

PostPosted: Tue Aug 11, 2015 2:54 pm
by mougino
Ok, pf_mount not needed I can live with that...

But then the next line of code in jvideo4.ino's setup() is
int a = PFFS.begin(10, rx, tx);

and neither rx nor tx are defined anywhere...
I saw that your ino file includes Myndale's "TimerOne.h" so I searched the forum and finally managed to find and download it, but there again no mention of rx nor tx :(

Are there any other files needed to make jvideo4.ino work ?
As is, it's not possible to compile.

Re: Any Petit FatFs example?

PostPosted: Tue Aug 11, 2015 2:54 pm
by Valden
Thanks for that lib jonnection. The lack of the need for a buffer (aka 512 of free RAM) is a very good advantage. If someone is interested, I managed to make the library work using the sample you provided :

Code: Select all
#include <SPI.h>
#include <petit_fatfs.h>
#include <Gamebuino.h>

FATFS fs;
FRESULT res;
WORD br;

Gamebuino gb;
void setup() {
  Serial.begin(9600);
  gb.begin();
  spi_init();

  PFFS.begin(10, rx, tx);
 
// There is where you can load your file:

  res = pf_open("MHQ0000.DAT");
  if (res) {Serial.print(F("Error !"));Serial.print(res);while (1);}
}

void spi_init()
{
  pinMode(10, OUTPUT); // 10 = SS = Slave select of SD
  pinMode(11, OUTPUT); // MOSI data to SD
  pinMode(12, INPUT);  // PB 4 - MISO data from SD
  pinMode(13, OUTPUT); // SCLK
 
  // SET HARDWARE SPI in Master & enabled
  // default speed is Clock/4 = 4 Mhz which is maximum for nokia lcd
  SPCR = _BV(MSTR) | _BV(SPE);      // Master mode, SPI enable, clock speed MCU_XTAL/4
}

byte rx()
{
  // The SPI Data Register is a read/write register
  // used for data transfer between the Register File and the SPI Shift Register.
  // Writing to the register initiates data transmission. Reading the register causes the Shift Register receive buffer to be read.
  SPDR = 0xFF; // dummy byte to initiate reading
  // loop_until_bit_is_set is an AVR libc macro
  // SPSR is SPI status register, SPIF is SPI interrupt flag, that is set after transmission is complete
  loop_until_bit_is_set(SPSR, SPIF);
  return SPDR; //return the SPDR (= value back from slave)
}

void tx(byte d)
{
  SPDR = d;
  loop_until_bit_is_set(SPSR, SPIF);
}