Pages: [1]   Go Down
Author Topic: TinyFAT Library  (Read 6909 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Jr. Member
**
Karma: 1
Posts: 70
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset



The SDuFAT library has some basic function for file log, can not meet some more complex requirements. Now Henning Karlsen publish a TinyFAT library and it’s really more powerful than former. And it had been designed to integrate with ITDB02_Graph and ITDB02_Graph16 - so now you can easy to use this library to read out the image in the SD cards and display on ITBD02 LCD module.

The library supports FAT16 formatted SD cards up to 2GB in size. 4GB FAT16 formatted SD cards might work, but is untested. Long filenames are not supported. Keep you filenames compliant with the old 8.3 standard.

The SD card should be connected to the SPI-pins on your Arduino. The Stackable SD Card Shield is compatible with it.


Structures:

file.buffer[];
Buffer used for reading and writing SD-card sectors.
Variables:
file.buffer[0-511]:  Byte-array to hold one sector of data.

file.MBR;
Master Boot Record of the SD card.
Variables:
Part1Type:  Partition1 Type. Only types 0×04, 0×06 and 0×86 can be used.
part1Start: First sector of Partition1.
part1Size:  Number of sectors in Partition1.

file.BS;
Boot Sector of Partition1.
Variables:

sectorsPerCluster:   Number of sectors per cluster.
reservedSectors:   Number of reserved sectors.
fatCopies:   Number of File Allocation Tables in partition.  Almost always 2.
rootDirectoryEntries:   Maximum number of root directory entries.
totalFilesystemSectors:   Total number of sectors available to the file system.
sectorsPerFAT:   Sectors per File Allocation Table.
hiddenSectors:   Number of hidden sectors preceding the partition that contains this FAT volume.
partitionSerialNum:   Partition serial number.
fat1Start:   First sector of primary File Allocation Table.
fat2Start :   First sector of secondary File Allocation Table.
partitionSize:   Size of partition in MB.

file.DE;
Directory Entry structure. Used by findFirstFile() and findNextFile().
Variables:

filename:   Char array containing the file’s name.
fileext:   Char array containing the file’s extension.
attributes:   File attributes.
time:   File creation time (encoded).
date:   File creation date (encoded).
startCluster:   First cluster of file data.
fileSize:   File size in bytes.

Functions:

file.initFAT(spispeed) : Initialize the interface, and connect to the SD card.

file.findFirstFile(DEstruct) : Find information about the first file in the root directory.

file.findNextFile(DEstruct) : Find information about the next file in the root directory.

file.openFile(filename, filemode) : Open a file for reading.

file.readBinary() : Read the next sector of an open binary file.

file.readLn(buffer, bufSize) : Read the next line of text from an open text-file.

file.writeLn(text) : Append a line of text to a text-file.

file.closeFile() : Close the currently open file.

file.exists(filename) : Check if a file exists.

file.rename(from-name, to-name) : Rename a file.

file.delFile(filename) : Delete a file.

file.create(filename) : Create a new, empty file.
« Last Edit: February 27, 2011, 02:02:21 pm by ITead » Logged

Itead Studio - Make innovation easier

Offline Offline
Jr. Member
**
Karma: 1
Posts: 58
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I am using an ITDB02S with a Mega2560. I can make it work with Henning Karlsen's libraries. Graphics and touchscreen are fine. I can access the SD card with the tinyFAT library, but only if I use the default SPI select ( pin 53 on the Mega). However, I have multiple SPI devices and I need to use a different select pin. The tinyFAT setSSpin() function is not helpful. Is there a way to do this?
Logged

0
Offline Offline
Sr. Member
****
Karma: 7
Posts: 476
what?
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Yes I would like to know that too, im using it with ethernet shield, SD works fine without the shield but when I use file.setSSpin(smiley-cool; // pin 8 SD SS pin
the SD doesn't work
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 614
Posts: 49343
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
but when I use file.setSSpin(smiley-cool; // pin 8 SD SS pin
the SD doesn't work
I don't think you can use the smiley face pin as a slave select pin.
Logged

0
Offline Offline
Sr. Member
****
Karma: 7
Posts: 476
what?
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Bugger, that's why it's not working then...

It should have read file.setSSpin();
when i want to change SD SS to pin 8 it hangs, i dont know if its the SD or duemilanove thats hanging, SD & ethernet work seperatly with SS on pin 10 but not together even if i set SS to 8 or 9, Im starting to get anoyed with it now

Logged

Offline Offline
Jr. Member
**
Karma: 1
Posts: 58
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

For the SPI to work, pin 10 (Uno, etc), or pin 53 (Mega), must be set to output, whatever pin you eventually assign to SS. If this is done, you should be able to use pins 8 or 9, as long as they are also set as outputs.  As for using other pins as SS, or debugging, keep reading.

TinyFAT uses an auxiliary file called mmc.cpp.  This is where the SS initialization and SPI handshaking occur. For my Mega application, I found that it was reassigning the SS pin, but not correctly setting the DDR register  associated with the new pin's port. This is not very complicated. Each physical I/O pin on the Arduino belongs to a port (PORTA,PORTB,PORTC,...) and each port has a data direction register associated with it  (DDRA, DDRB, ...).

mmc.cpp does its SPI protocol stuff by port manipulation.  It needs to know 3 things at initialization: The SS pin, the PORT associated with the SS pin, the DDR for that port. For the most Arduinos except the Mega, this defaults to pin 10, PORTB, DDRB. Pins 8 and 9 should also be PORTB and DDRB. For the Mega, the default SS is pin 53, PORTB, DDRB.  Other pins may have other ports and DDR's. But you can use any other pin available if you just make sure mmc.cpp is using the correct 3 parameters for its calls. I was able to do this for the Mega by cleaning up mmc.cpp.

Here are the relevant parts of mmc.cpp that I changed. I have set it to use pin 42 as the default SS for the Mega, but it can be set to any pin.

Code:
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
byte SS= 7;  //using PL7 (D42) as SS
byte SSlegacy = 0; // bit position of chip select on the legacy SPI port
// for Mega: PB0 (pin d53), for Uno: PB2 (pin d10)

volatile uint8_t *SSPORT = &PORTL;
volatile uint8_t *SSDDR =  &DDRL;
#define MOSI 2
#define MISO 3
#define SCK 1
#else
    byte SS = 2;
byte SSlegacy = 2;
volatile uint8_t *SSPORT = &PORTB;
volatile uint8_t *SSDDR =  &DDRB;
#define MOSI 3
#define MISO 4
#define SCK        5
#endif

byte mmc::initialize(byte speed) {
  byte  i;
  uint16_t counter;
  uint32_t answer;

  disk_state = DISK_ERROR;

  // setup SPI I/O pins

  PORTB |=  _BV(SCK)  | _BV(SSlegacy) | _BV(MISO); // set SCK, pullup on MISO
  DDRB  |=  _BV(SCK)   | _BV(SSlegacy) | _BV(MOSI); // set SCK/MOSI as output
  DDRB  &= ~_BV(MISO);
// set MISO as input

  *SSPORT |=  _BV(SS); // set SS
  *SSDDR  |=  _BV(SS) ; // set SS as output

  // setup SPI interface:
  //   interrupts disabled, SPI enabled, MSB first, master mode,
  //   leading edge rising, sample on leading edge, clock = f/4,
  SPCR = B01010000 | speed;

  // Enable SPI double speed mode -> clock = f/8
  //  SPSR = _BV(SPI2X);

  // clear status
  i = SPSR;

  // clear recieve buffer
  i = SPDR;

  SPI_SS_HIGH();

  // Send 80 clks
  for (i=0; i<10; i++) {
    spiTransferByte(0xFF);
  }

  // Reset card
  i = sendCommand(GO_IDLE_STATE, 0, 1);
  if (i != 1) {

    return STA_NOINIT | STA_NODISK;
  }

  counter = 0xffff;
  // According to the spec READ_OCR should work at this point
  // without retries. One of my Sandisk-cards thinks otherwise.
  do {
    // Send CMD58: READ_OCR
    i = sendCommand(READ_OCR, 0, 0);
    if (i > 1) {
      // kills my Sandisk 1G which requires the retries in the first place
      // deselectCard();
    }
  }
  while (i > 1 && counter-- > 0);

  if (counter > 0) {
    answer = spiTransferLong(0);

    // See if the card likes our supply voltage
    if (!(answer & SD_SUPPLY_VOLTAGE)) {
      // The code isn't set up to completely ignore the card,
      // but at least report it as nonworking
      deselectCard();
      return STA_NOINIT | STA_NODISK;
    }
  }

  // Keep sending CMD1 (SEND_OP_COND) command until zero response
  counter = 0xffff;
  do {
    i = sendCommand(SEND_OP_COND, 1L<<30, 1);
    counter--;
  }
  while (i != 0 && counter > 0);

  if (counter==0) {
    return STA_NOINIT | STA_NODISK;
  }

  // Send MMC CMD16(SET_BLOCKLEN) to 512 bytes
  i = sendCommand(SET_BLOCKLEN, 512, 1);
  if (i != 0) {
    return STA_NOINIT | STA_NODISK;
  }

  // Thats it!
  disk_state = DISK_OK;
  return RES_OK;
}
void SPI_SS_HIGH(){ *SSPORT |= _BV(SS); }

void SPI_SS_LOW(){ *SSPORT &= ~_BV(SS);}

static void deselectCard(void) {
  // Send 8 clock cycles
  SPI_SS_HIGH();
  spiTransferByte(0xff);
}

byte mmc::initialize(byte speed) {
  byte  i;
  uint16_t counter;
  uint32_t answer;

  disk_state = DISK_ERROR;

  // setup SPI I/O pins

  PORTB |=  _BV(SCK)  | _BV(SSlegacy) | _BV(MISO); // set SCK, pullup on MISO
  DDRB  |=  _BV(SCK)   | _BV(SSlegacy) | _BV(MOSI); // set SCK/MOSI as output
  DDRB  &= ~_BV(MISO);
// set MISO as input

  *SSPORT |=  _BV(SS); // set SS
  *SSDDR  |=  _BV(SS) ; // set SS as output

  // setup SPI interface:
  //   interrupts disabled, SPI enabled, MSB first, master mode,
  //   leading edge rising, sample on leading edge, clock = f/4,
  SPCR = B01010000 | speed;

  // Enable SPI double speed mode -> clock = f/8
  //  SPSR = _BV(SPI2X);

  // clear status
  i = SPSR;

  // clear recieve buffer
  i = SPDR;

  SPI_SS_HIGH();

  // Send 80 clks
  for (i=0; i<10; i++) {
    spiTransferByte(0xFF);
  }


void mmc::setSSpin(const uint8_t _pin) {
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
if (_pin==53) {
SSPORT = &PORTB;
SSDDR = &DDRB;
SS=0;
}
else if ((_pin>=42) and (_pin<=49)) {
SSPORT = &PORTL;
SSDDR = &DDRL;
SS= 49 - _pin;
}
#else
if ((_pin>=8) and (_pin<=10)) {
SS=_pin-8;
SSPORT = &PORTB;
SSDDR = &DDRB;
}
#endif
}
Logged

Offline Offline
Jr. Member
**
Karma: 1
Posts: 58
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

In the above posted code, in the method mmc::setSSpin(pin), I am only allowing the Mega SS pin to range through PORTL (pins 42-49) and the Uno SS pin to range through PORTB pins 8-10. To use other pins outside this range for SS, just expand the conditional to assign SSPORT and SSDDR to the proper values for the pins you might want to use. You will need to look at an Arduino pin map.   I reserved PORTL for SS choices for my Mega application. That gave me 8 more SS pins, so potentially 8 more SPI devices beyond the default device. So I didn't bother to code for more options.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

any someone have a simulation for  Stackable SD Card Shield if we use Arduino?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 36
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Sorry if this sounds like a dumb question, but I'm new to this library and to writing to SD cards in general.

It appears that using file.writeLn(text); does ONLY that ... writes text to a file.  I am wanting to log data from a magnetometer and need to create a data string to be written in CSV format.  As an example, I want to execute something like this...

String datastring = (valuex + "," + valuey + "," + valuez);
file.writeLn(datastring);

But the library won't allow anything except text between quotes.  This to me seems to be pretty useless if I cannot pass anything but ASCII text to the function.  Is there a method to create a char array containing my data and the comma seporator, and append each character to the same line, and then a CR / LF at the end of the array?  This is so frustrating because I spent a great deal of time getting SPI to work with my shield and SD card.  The datalogging is the only obstacle in the way of completing this project !!!

Any advice would be most appreciated...
Logged

Sydney, Australia
Offline Offline
Edison Member
*
Karma: 33
Posts: 1273
Big things come in large packages
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Look at sprintf()   You format a string that you can then write to the file.
Logged

Arduino libraries http://arduinocode.codeplex.com
Parola hardware & library http://parola.codeplex.com

Offline Offline
Newbie
*
Karma: 0
Posts: 36
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks, but I'm coding in the arduino IDE wiring language.  I will see if there is a comparable function.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 614
Posts: 49343
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Sorry if this sounds like a dumb question
It is, since the class you are referring to doesn't even HAVE a writeLn() method.

The print() and println() methods that it DOES have KNOW how to convert floats, doubles, ints, and bazookas (just kidding) to text.

Quote
This to me seems to be pretty useless if I cannot pass anything but ASCII text to the function.
You don't like the String library? Write your own, then.

Better yet, just don't use it. You don't need it.

Quote
Is there a method to create a char array containing my data and the comma seporator, and append each character to the same line, and then a CR / LF at the end of the array?
Of course there is, and marco_c pointed it out.

Quote
Thanks, but I'm coding in the arduino IDE wiring language.
What the hell is that? The Arduino is programmed using C++, not Java, not wiring, not some proprietary language. Plain C++.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 36
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I must have struck a nerve with someone.  I meant no disrespect...just that I was trying to figure out how to use tinyFat to write data not text to a file.  I know the arduino is a C environment, but if you look on the official arduino page they call it a 'wiring' language.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 1
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Como estan amigos .....me podrian ayudar con un problema que tengo..... el problema es que utilizo la libreria tinyFAT y la biblioteca UTouch con un Arduino Mega2560 y una pantalla 3.2" LCD TF Card Shiel REV.B al momento de cargar el progama bien solo me funciona la libreria tinyFAT y la de UTouch no me funciona y asi mismo me funciona la UTouch y la tinyFAT no me funciona el problema radica que estas librerias utilizan el mismo MOSI, MISO y SCK y al momento de activar ya sea el pin para el touch o el pin de sd solo me funciona uno y no los dos a la ves en el mismo programa espero me puedan ayudar y de antemano estare muy agradecido...............

How are friends ..... I could help with a problem that I have ..... the problem is that I use the library and tinyFAT uTouch Mega2560 library with Arduino and a screen 3.2 "LCD TF Card Shiel REV.B to time to load the progam works well only me and the library tinyFAT uTouch not work and so I myself uTouch works and does not work tinyFAT me the problem is that these libraries use the same MOSI, MISO and SCK and when activate either touch or pin for pin sd works just me one and not to see the two in the same program and I hope I can help I will be very grateful in advance ............ ...
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 1
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Estimates

It happens the same as Esllerena, combining tinyFAT library and uTouch the pictures are displayed correctly stops working but the touch part must be that both the touch part to the SDcard used the same pins MOSI, MISO and SCK , note that I’m using ARDUINO MEGA board. (separate libraries work properly)

Please show your support and fix this, or another way to handle images in raw format and can be used uTouch .. thanks for your help

- See more at: http://blog.lincomatic.com/?p=1074#sthash.rqzXOtS8.dpuf
Logged

Pages: [1]   Go Up
Jump to: