Pages: [1]   Go Down
Author Topic: Reading/writing struct to sd card  (Read 1177 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 33
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

Is it anyhow possible to write and read a struct to a sd card? My struct looks like this:
Code:
struct Pattern {
  byte length;
  byte shuffle;
  byte steps[12][64];
  byte accentVelocity[12][2];
  byte doubleSpeed;
};

I would like to have one file for each pattern/struct on my sd card, but simply don't know how to do that.
Logged

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

A struct is just an area of memory. So if the SD library allows you to write a block of bytes (or an array of bytes), then you need to have something like this

Code:
writefunctionname((uint8_t *)&Pattern_var, sizeof(Pattern_var)/sizeof(uint8_t));

In other words, a pointer to the structure is cast as a pointer to whatever the function will take (uint8_t, int, or other). The number of these elements to be written is the sizeof the structure divided by the sizeof the element to be written. In this case the divisor would be 1 as uint8_t is size 1 byte.

If block writes are not available then a similar thing can be done but you need to write each element of the memory buffer individually (usually using a loop), incrementing the memory pointer for each element.
« Last Edit: October 11, 2013, 01:19:27 am by marco_c » Logged

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

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

Okay,thanks. I would like to save them in a file, so that the user can backup the patterns. How can I write and read multiple bytes into one file? file.write only writes one byte or one array of bytes into a file.

Edit. I got it.
Is this the best and fastest way to do?
Code:
void savePatternToFile() {
  File patternFile = SD.open("FF.txt", FILE_WRITE);
  patternFile.seek(0);
  patternFile.write(pattern.length);
  patternFile.write(pattern.shuffle);
  patternFile.write(pattern.doubleSpeed);
  for (int a = 0; a < 12; a++) {
    for (int i = 0; i < 64; i++) patternFile.write(pattern.steps[a][i]);
  }
  for (int a = 0; a < 12; a++) {
    for (int i = 0; i < 2; i++) {
      patternFile.write(pattern.flamSetting[a][i]);
    }
  }
  patternFile.close();
}

void readPattern(){
  File patternFile = SD.open("FF.txt", FILE_WRITE);
  patternFile.seek(0);
  pattern.length = patternFile.read();
  pattern.shuffle = patternFile.read();
  pattern.doubleSpeed = patternFile.read();
  for (int a = 0; a < 12; a++) {
    for (int i = 0; i < 64; i++) pattern.steps[a][i] = patternFile.read();
  }
  for (int a = 0; a < 12; a++) {
    for (int i = 0; i < 2; i++) {
      pattern.accentVelocity[a][i] = patternFile.read();
    }
  }
    patternFile.close();
}
« Last Edit: October 10, 2013, 11:31:17 pm by flocked » Logged

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

Quote
How can I write and read multiple bytes into one file? file.write only writes one byte or one array of bytes into a file.
An array is just a consecutive collection of bytes, just like the struct. marco_c showed you how to write it.
Logged

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

The SD library does have a block write function, pretty much like in my first reply. Extract from the library online manual:

Quote
Syntax
file.write(data)
file.write(buf, len)

Parameters
file: an instance of the File class (returned by SD.open())
data: the byte, char, or string (char *) to write
buf: an array of characters or bytes
len: the number of elements in buf

Using this method would be more efficient and faster, as you do it all in one statement.
Logged

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

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

marco_c : Thanks!

Code:
patternFile.write((uint8_t *)&pattern, sizeof(pattern)/sizeof(uint8_t));

But how can I read this again and assign it to the pattern struct?

pattern = patternFile.read() is of course not working.

Do i need to:
Code:
patternFile.seek(0);
pattern.length = patternFile.read();
pattern.shuffle = patternFile.read();
  for (int a = 0; a < 12; a++) {
    for (int i = 0; i < 64; i++) pattern.steps[a][i] = patternFile.read();
  }
//etc.…
« Last Edit: October 11, 2013, 02:16:22 am by flocked » Logged

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

Most good libraries have a block read as well, to match the block write. In this case you will need to use a loop to read all the data in one byte at a time. Set a uint8_t pointer to the address of the data/struct and then for each byte you read, assign it to the 'pointed' location and increment the pointer, repeat.
Logged

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

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

Okay, I took a look into sdfatlib and it has block read. But I still can't get it to work.
Code:
pattern = patternFile.read((uint8_t *)&pattern, sizeof(pattern)/sizeof(uint8_t));
gives me: 
Quote
error: no match for 'operator=' in 'pattern = patternFile.SdFile::<anonymous>.SdBaseFile::read(((void*)((uint8_t*)(& pattern))), 819u)'
note: candidates are: Pattern& Pattern::operator=(const Pattern&)
Logged

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

There is no = as per the error message. Think about what the function is doing. It is filling the memory from the SD card, so why are you needing to assign anything? Also, look at the function documentation to see what the return value  is.  People who write libraries document stuff so you can us their libraries more easily, but you do need to make the effort to read up on it to make sure you are using it properly.
Logged

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

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

I'm sorry. I only took a quick look and yeah, I forgot to read the description :/

Thanks helping me, it works smiley
Logged

Pages: [1]   Go Up
Jump to: