snowsh
Well-known member
right, I have been fighting this one for a few days now....
I have several different structs that make up the core of my project...
here is an example of one of my structs:
Its "library" members are stored in EXTMEM. the current pattern is stored in SRAM so its fast. any time a pattern is changed, I siply copy from the libray the requested pattern into currentPattern. All good. I can store them also to SD card for backup, and when the device is started it loads all the data from the SD card back into the EXTMEM members... perfect. happy me.
However......
this struct does not perform.....
the obvious difference here is that the struct contains a multidimensional array.....
I get no errors in complile, and otherwise it works perfectly well. The program is quite happy with the multidimensional array.
I have a complicated "boot" sequence that checks for the sd card, if its there, it checks for an init file which says if the SD card contains the data, ie "formatted" for my project....
if the init file is not present, it runs through all the struct members and stores them to the SD card during startup. As the program is run, and the user makes any edits, the data for the given pattern for example is updated in EXTMEM or wherever the particular location is the given data. At the same time it is also saved back to the SD card so any edits are stored for the next time the device is booted up...
In this particular instance, with the multi dimensional array, when the device starts up and tries to reload the data back from SD to the EXTMEM location, it fails. the only error I can get is "Unable to read the example block in dru_000.txt" which is attached to the loop checking against the data size:
When I check in notepadd++ and veiw the data on the SD card in hex, I see the data has not been written correctly to the SD card....
I ran an experiment by placing a multidimensional array to the other struct example, and yes, it fails in the same way......
here are two snippets from my code, the first saves the data (it could be a struct, or an array - I have had a headache with this so I gave up and simply wrote different functions to deal with each struct.... I hope to tidy that later as I improve my c++ - this was all so easy with PHP - not that I am going back. I am really enjoying the challenge of C++
anyway....
function to store to SD card:
function example to read from SD card and store back to EXTMEM
I suspect the issue is that I have yet to properly get my head around pointers etc.... I see & and * and am still confused..... I hope that someone here can spot the issue and help me on my way.
if you are so inclined, there is a video of my project here: https://www.picuki.com/media/2603517577921609539 sorry for the sound, it seems my phone needs replacing
I just realised I didnt show the functions that deal with this particular struct. here they are:
Save:
Load:
I have several different structs that make up the core of my project...
here is an example of one of my structs:
Code:
struct mypattern {
uint8_t note[MAX_NUMBER_OF_STEPS];
int8_t octave[MAX_NUMBER_OF_STEPS]; // -1 = down 0 = normal 1 = up
int8_t transpose;
uint8_t accent[MAX_NUMBER_OF_STEPS];
bool slide[MAX_NUMBER_OF_STEPS];
uint8_t noteLength[MAX_NUMBER_OF_STEPS];
uint8_t patternLength;
char patternName[PATTERN_NAME_LENGTH];
} currentPattern;
EXTMEM struct mypattern mypatterns[NUMBER_OF_PATTERNS];
Its "library" members are stored in EXTMEM. the current pattern is stored in SRAM so its fast. any time a pattern is changed, I siply copy from the libray the requested pattern into currentPattern. All good. I can store them also to SD card for backup, and when the device is started it loads all the data from the SD card back into the EXTMEM members... perfect. happy me.
However......
this struct does not perform.....
Code:
struct drummerLibraryStruct {
char title[DRUMMER_PATTERN_NAME_LENGTH] = {'n','a','m','e',' ','h','e','r','e',' '};
uint8_t pattern[NUMBER_OF_DRUMMER_INSTRUMENTS][NUMBER_OF_DRUMMER_STEPS]; // this is the offender!
};
EXTMEM struct drummerLibraryStruct drummerLibrary[NUMBER_OF_DRUMMER_PATTERNS];
the obvious difference here is that the struct contains a multidimensional array.....
I get no errors in complile, and otherwise it works perfectly well. The program is quite happy with the multidimensional array.
I have a complicated "boot" sequence that checks for the sd card, if its there, it checks for an init file which says if the SD card contains the data, ie "formatted" for my project....
if the init file is not present, it runs through all the struct members and stores them to the SD card during startup. As the program is run, and the user makes any edits, the data for the given pattern for example is updated in EXTMEM or wherever the particular location is the given data. At the same time it is also saved back to the SD card so any edits are stored for the next time the device is booted up...
In this particular instance, with the multi dimensional array, when the device starts up and tries to reload the data back from SD to the EXTMEM location, it fails. the only error I can get is "Unable to read the example block in dru_000.txt" which is attached to the loop checking against the data size:
Code:
sdfile.available()
When I check in notepadd++ and veiw the data on the SD card in hex, I see the data has not been written correctly to the SD card....
I ran an experiment by placing a multidimensional array to the other struct example, and yes, it fails in the same way......
here are two snippets from my code, the first saves the data (it could be a struct, or an array - I have had a headache with this so I gave up and simply wrote different functions to deal with each struct.... I hope to tidy that later as I improve my c++ - this was all so easy with PHP - not that I am going back. I am really enjoying the challenge of C++
anyway....
function to store to SD card:
Code:
void savePatternSD(int i)
{
Serial.print( F("saving to SD card : "));
Serial.println(i);
getFilename(i, SEQUENCER);
addNames(i, SEQUENCER);
byte *buff = (byte *) &mypatterns[i]; // to access example as bytes
File sdfile; // File object
char fname[ 14 ]; // even # of bytes big enough to hold 8.3 filename and terminator
strcpy( fname, filename);
sdfile = SD.open( fname, FILE_WRITE );
if (!sdfile) Serial.println( F("error cannot open sd card"));
if (!sdfile.seek( 0 )) Serial.println( F("error cannot seek sd card"));
if (!sdfile.write( buff, sizeof( mypatterns[i] ))) Serial.println( F("error cannot write sd card"));
sdfile.close();
}
function example to read from SD card and store back to EXTMEM
Code:
void sdOpenPatternFile(int i, int type)
{
getFilename(i, type);
byte count;
File sdfile; // File object
char fname[ 14 ]; // even # of bytes big enough to hold 8.3 filename and terminator
strcpy( fname, filename );
sdfile = SD.open( fname, FILE_READ ); // try to open text.txt // ========== SD open file to read ====================================
if ( !sdfile ) // if test.txt not found, notify and change state
{
Serial.print( F("Unable to open for read: ") );
Serial.println( fname );
while ( 1 );
}
byte *buff = (byte *) &myPatterns[i]; // to access example as bytes // ========== SD read file to struct ==================================
for ( count = 0; count < sizeof( mypatterns[i] ); count++ )
{
if ( sdfile.available())
{
*( buff + count ) = sdfile.read();
}
else
{
Serial.print( F( "Unable to read the example block in " ));
Serial.println( fname );
Serial.print( count, DEC );
Serial.println( F( " bytes read." ));
while ( 1 );
}
}
sdfile.close();
}
I suspect the issue is that I have yet to properly get my head around pointers etc.... I see & and * and am still confused..... I hope that someone here can spot the issue and help me on my way.
if you are so inclined, there is a video of my project here: https://www.picuki.com/media/2603517577921609539 sorry for the sound, it seems my phone needs replacing
I just realised I didnt show the functions that deal with this particular struct. here they are:
Save:
Code:
void saveDrummerPatternSD(int i)
{
Serial.print( F("saving drummer pattern to SD card : "));
Serial.println(i);
getFilename(i, DRUMMER);
addNames(i, DRUMMER);
byte *buff = (byte *) &drummerLibrary[i].pattern; // to access example as bytes
File sdfile; // File object
char fname[ 14 ]; // even # of bytes big enough to hold 8.3 filename and terminator
strcpy( fname, filename);
Serial.print("size: ");
Serial.println(sizeof(buff));
sdfile = SD.open( fname, FILE_WRITE );
if (!sdfile) Serial.println( F("drummer pattern error cannot open sd card"));
if (!sdfile.seek( 0 )) Serial.println( F("drummer pattern error cannot seek sd card"));
if (!sdfile.write( buff, sizeof( drummerLibrary[i].pattern ))) Serial.println( F("error cannot write sd card"));
sdfile.close();
}
Load:
Code:
void sdOpenDrummerFile(int i, int type)
{
getFilename(i, type);
byte count;
File sdfile; // File object
char fname[ 14 ]; // even # of bytes big enough to hold 8.3 filename and terminator
strcpy( fname, filename );
sdfile = SD.open( fname, FILE_READ ); // try to open text.txt // ========== SD open file to read ====================================
if ( !sdfile ) // if test.txt not found, notify and change state
{
Serial.print( "Unable to open for read: " );
Serial.println( fname );
while ( 1 );
}
byte *buff = (byte *) &drummerLibrary[i].pattern; // to access example as bytes // ========== SD read file to struct ==================================
for ( count = 0; count < sizeof( drummerLibrary[i].pattern ); count++ )
{
if ( sdfile.available())
{
*( buff + count ) = sdfile.read();
}
else
{
Serial.print( F( "Unable to read the example block in " ));
Serial.println( fname );
Serial.print( count, DEC );
Serial.println( F( " bytes read." ));
while ( 1 );
}
}
sdfile.close();
}
Last edited: