Pages: [1]   Go Down
Author Topic: EEPROM_writeAnything - slightly improved  (Read 1016 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

just like to share a slightly improvement to EEPROM_writeAnything. Lets assume you're using a struct to store your data to the EEPROM, for instance:

Code:
struct config_t
{
  unsigned int param1;
  unsigned int param2;
  unsigned int param3;
  int sockets[63];
} cfg;

The obvious drawback of the original EEPROM_writeAnything lies in always writing out the whole data to the EEPROM, regardless of the actual changed data. So here's my simple (but effective) solution:

Code:
template <class T> int EEPROM_writeAnything(int ee, const T& value)
{
  const byte* p = (const byte*)(const void*)&value;
  byte c;  // Comparison byte
  int i;
  for (i = 0; i < sizeof(value); i++) {
    c = EEPROM.read(ee);
    if(c != *p) {
      EEPROM.write(ee, *p);
    }
    *p++;
    ee++;
  }
  return i;
}

template <class T> int EEPROM_readAnything(int ee, T& value)
{
  byte* p = (byte*)(void*)&value;
  int i;
  for (i = 0; i < sizeof(value); i++)
    *p++ = EEPROM.read(ee++);
  return i;
}

The function reads and compares each byte, writing only different data to the EEPROM. This will drasticially improve write performance with bigger data structures, and increases the overall lifetime of the EEPROM. ;-)

Cheers,
-- Bastian
Logged

0
Offline Offline
Faraday Member
**
Karma: 16
Posts: 2855
ruggedcircuits.com
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

That is a nice idea, though have you noticed any increase in size of code or RAM usage because of the template usage? Would it not be simpler (trying to avoid templates here) to just pass a "const void *" to EEPROM_writeAnything?

--
The Ruggeduino: compatible with Arduino UNO, 24V operation, all I/O's fused and protected
Logged

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

Interesting point, I'll check that. Just copied the code from the playground: http://www.arduino.cc/playground/Code/EEPROMWriteAnything. Using templates seems a bit overkill to me as well.
« Last Edit: May 29, 2011, 02:02:48 pm by mooney » Logged

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

Made a quick test, first using templates:

Code:
template <class T> int EEPROM_writeAnything(int ee, const T& value)
{
    (...)
}
Binary sketch size: 15528 bytes
Available RAM: 438 bytes

...next without:

Code:
int EEPROM_writeAnything(int ee, const config_t& value)
{
    (...)
}
Binary sketch size: 15682 bytes
Available RAM: 438 bytes

Surprisingly, using templates saves me 154 bytes, the RAM doesn't seem to be affected at all...
Logged

0
Offline Offline
Faraday Member
**
Karma: 16
Posts: 2855
ruggedcircuits.com
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Cool! Yay for GCC.

Personally I would still prefer a "const void *" version ensuring that only 1 instance of the code is ever instantiated. I'd be worried with the template version that if you try to use the functions with more than one type it will insert the code twice.

--
The Flexible MIDI Shield: MIDI IN/OUT, stacking headers, your choice of I/O pins
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 217
Posts: 13739
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Besides a memory test, do you have some figures about the speed differences?  

I think of a testcase with a 20 bytes struct or array ... ( don't have an Arduino free at the moment smiley-sad

# same, # time without read, time with read
0, t1, t2
1,
...
20,

TIA,
Rob

The theoretical value : http://www.arduino.cc/en/Reference/EEPROMWrite => An EEPROM write takes 3.3 ms to complete
Can't find the value for EEPROMRead() ??

---

the char c is not needed?

Code:
template <class T> int EEPROM_writeAnything(int ee, const T& value)
{
  const byte* p = (const byte*)(const void*)&value;
  int i;
  for (i = 0; i < sizeof(value); i++) {
    if (EEPROM.read(ee) != *p) EEPROM.write(ee, *p);
    }
    *p++;
    ee++;
  }
  return i;
}
« Last Edit: May 29, 2011, 05:10:41 pm by robtillaart » Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 217
Posts: 13739
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Maybe it is better to change it one level lower in the EEPROM class in EEPROM.cpp, Then other EEPROM applications would benefit from it too!

from EEPROM.cpp
Code:
uint8_t EEPROMClass::read(int address)
{
return eeprom_read_byte((unsigned char *) address);
}

void EEPROMClass::write(int address, uint8_t value)
{
eeprom_write_byte((unsigned char *) address, value);
}

to

Code:
uint8_t EEPROMClass::read(int address)
{
return eeprom_read_byte((unsigned char *) address);
}

void EEPROMClass::write(int address, uint8_t value)
{
         if (eeprom_read_byte((unsigned char *) address) != value) eeprom_write_byte((unsigned char *) address, value);
}
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Pages: [1]   Go Up
Jump to: