I wrote a library for the External Memory interface module on the mega1280/2560. I wanted to incorperate templates into the library so I can pass any type as an argument to the functions. Someone suggested EEPROMWriteAnything from the Arduino Playground. I used the template parts of it in my library. My library and sketch are below. I really don't understand templates. I just copied that part into my library. I got it to compile and work, almost. In the sketch I write to external memory twice. The first time I pass a uint8_t type (20) to the write function, the second time I pass a uint16_t type (256). Then I read back the data from the same two addresses I had written to. In the case of the uint8_t type the data returns correctly (20). In the case of the uint16_t type it returns incorrectly (0).
Here's the sketch:
#include <ExMem.h>
void setup()
{
Serial.begin(115200);
// Enables the interface with two sectors with the upper/lower boundry at 0x8000 and no wait-states
ExMem.enable(16, 0x8000, 0, 0);
uint8_t x1 = 20;
uint16_t y1 = 256;
ExMem.write(0, 0x0020, x1); // write to lower sector address 0x0020
ExMem.write(0, 0x0030, y1); // write to lower sector address 0x0030
// varibles to hold data read
uint8_t x2;
uint16_t y2;
// The function places the data in the supplied variable
// and returns the number of bytes read.
Serial.println(ExMem.read(0, 0x0020, x2), DEC);
Serial.println(x2, DEC);
Serial.println(ExMem.read(0, 0x0030, y2), DEC);
Serial.println(y2, DEC);
}
void loop()
{
}
Sorry, I have to post twice, due to the size of the library.
In the serial monitor, when I run the sketch, I get
1
20
2
0
I should get
1
20
2
256
If I change the second write from uint16_t to uint8_t type it returns correctly. As I stated earlier templates are very confusing to me, but I almost have this working. Frustrating! I really do apreciate any help on this. The functions in question are the last two in the library. The rest of the library works fine.
If I break up the uint16_t type into two uint8_t types and write them seperately. It will read back in a uint16_t type as it should. So, the problem is in the write function. I've almost got it. I'll test some more and post back.
Not 100% sure about what's wrong here, but this line in read()
*pStore++ = (TYPE)(*pMemory);
looks suspicious to me.
You are "reconstructing" the type byte-by-byte, so you don't want to cast the bytes you read from the external memory to the full type.
Also, I noticed in write() you don't increase pData. I suspect you're writing only the first byte of "data".
Thank you very much! It finally works. As for the double cast, I'm not sure. Copied it from EEPROMWriteAnything. You've been a big help. If there's anything I can do for you...
I've found a small bug. If I pass data type char* to the write function, say char c1 = "hello world", it will return with a value of 2, meaning it wrote 2 bytes. Then I pass the read function a variable of char, say char c2, and read from the same address written to. It also returns with 2, meaning it read 2 bytes. But when I use Serial.print(c2), It prints "hello world" as it should. Why is it returning a value of 2 when it clearly is more. Float returns 4, as do double, long long returns 8, and uint8_t = 1 and uint16_t = 2, all as expected. So what's with char?
it will return with a value of 2, meaning it wrote 2 bytes.
The value 2 means that a pointer is 2 bytes. It has NOTHING to do with the amount of data pointed to.
To verify that, create an array of ints, and pass that, via a pointer, to the class. The array can have 27 elements in it, and you will still get a 2 back.
Hmmm... c1 = "hello world" is not quite right. Sad reality is that c == 'h'. "hello world" is a C-string literal, meaning it's a null-terminated string.
If you want to store a char you have to work with the C-string convention that says the string ends at the first null byte. At run time, the length of a char (i.e. the length of a C-string) must be determined with strlen() or equivalent method.
Be careful to store the final null byte or the string length, otherwise at read time you won't know where to stop or how many chars to read.
@PaulS
I suspected it had to do with the pointer to the string. Thanks for the reply.
@tuxduino
With this library I only need to know the location of the first address of the string. The write function, or I believe the string literal variable I pass to the function already adds the terminating null for me and the function writes all of it to memory. All I have to do to read the string back is pass the read function the first address of the string and an empty string literal variable to hold it. The read function puts every byte from the first address to the null byte into the variable. I only need to know the length of the string when writing to keep track of where the next unused address is at for the next write to avoid overlap.