diff --git a/libraries/EEPROM/examples/Example1_GetPut/Example1_GetPut.ino b/libraries/EEPROM/examples/Example1_GetPut/Example1_GetPut.ino index ea86af35..b7b07be6 100644 --- a/libraries/EEPROM/examples/Example1_GetPut/Example1_GetPut.ino +++ b/libraries/EEPROM/examples/Example1_GetPut/Example1_GetPut.ino @@ -25,7 +25,7 @@ void setup() { - Serial.begin(9600); + Serial.begin(115200); Serial.println("EEPROM Examples"); byte myValue1 = 200; diff --git a/libraries/EEPROM/examples/Example2_AllFunctions/Example2_AllFunctions.ino b/libraries/EEPROM/examples/Example2_AllFunctions/Example2_AllFunctions.ino index ce9f1536..98569180 100644 --- a/libraries/EEPROM/examples/Example2_AllFunctions/Example2_AllFunctions.ino +++ b/libraries/EEPROM/examples/Example2_AllFunctions/Example2_AllFunctions.ino @@ -23,14 +23,14 @@ void setup() { - Serial.begin(9600); + Serial.begin(115200); Serial.println("EEPROM Examples"); randomSeed(analogRead(A0)); long startTime; long endTime; - uint16_t randomLocation; + int randomLocation; //Test erase time startTime = millis(); @@ -53,6 +53,12 @@ void setup() Serial.printf("Write byte time: %dms\n", endTime - startTime); + startTime = millis(); + EEPROM.write(randomLocation, myValue1); //(location, data) + endTime = millis(); + + Serial.printf("Write identical byte to same location (should be ~1): %dms\n", endTime - startTime); + byte response1 = EEPROM.read(randomLocation); byte response2 = EEPROM.read(randomLocation + 1); Serial.printf("Location %d should be %d: %d\n\r", randomLocation, myValue1, response1); @@ -106,8 +112,8 @@ void setup() uint32_t myValue8 = 241544; randomLocation = random(0, AP3_FLASH_EEPROM_SIZE); - EEPROM.update(randomLocation, myValue7); - EEPROM.update(randomLocation + 4, myValue8); + EEPROM.put(randomLocation, myValue7); + EEPROM.put(randomLocation + 4, myValue8); int32_t response7; uint32_t response8; @@ -124,8 +130,8 @@ void setup() float myValue10 = 5.22; randomLocation = random(0, AP3_FLASH_EEPROM_SIZE); - EEPROM.update(randomLocation, myValue9); - EEPROM.update(randomLocation + 4, myValue10); + EEPROM.put(randomLocation, myValue9); + EEPROM.put(randomLocation + 4, myValue10); float response9; float response10; @@ -143,20 +149,50 @@ void setup() Serial.printf("Size of double: %d\n", sizeof(double)); double myValue11 = -290.3485723409857; double myValue12 = 384.95734987; + double myValue13 = 917.14159; + double myValue14 = 254.8877; randomLocation = random(0, AP3_FLASH_EEPROM_SIZE); - EEPROM.update(randomLocation, myValue11); - EEPROM.update(randomLocation + 8, myValue12); + startTime = millis(); + EEPROM.put(randomLocation, myValue11); + endTime = millis(); + Serial.printf("Time to record 64-bits: %dms\n", endTime - startTime); + + EEPROM.put(randomLocation + 8, myValue12); + EEPROM.put(EEPROM.length() - sizeof(myValue13), myValue13); //Test end of EEPROM space double response11; double response12; + double response13; EEPROM.get(randomLocation, response11); EEPROM.get(randomLocation + 8, response12); + EEPROM.get(EEPROM.length() - sizeof(myValue13), response13); Serial.printf("Location %d should be %lf: %lf\n", randomLocation, myValue11, response11); Serial.printf("Location %d should be %lf: %lf\n", randomLocation + 8, myValue12, response12); + Serial.printf("Edge of EEPROM %d should be %lf: %lf\n", EEPROM.length() - sizeof(myValue13), myValue13, response13); + + double response14; + EEPROM.put(EEPROM.length() - sizeof(myValue14), myValue14); //Test the re-write of a spot + EEPROM.get(EEPROM.length() - sizeof(myValue14), response14); + Serial.printf("Rewrite of %d should be %lf: %lf\n", EEPROM.length() - sizeof(myValue14), myValue14, response14); //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - Serial.println(); + Serial.println(""); + Serial.println("String test"); + + //String write test + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + char myString[19] = "How are you today?"; + randomLocation = random(0, AP3_FLASH_EEPROM_SIZE); + EEPROM.put(randomLocation, myString); + + char readMy[19]; + EEPROM.get(randomLocation, readMy); + Serial.printf("Location %d string should read 'How are you today?': ", randomLocation); + Serial.println(readMy); + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + + Serial.println(""); Serial.print("Flash Contents:"); for (uint16_t x = 0; x < 8 * 4; x += 4) { diff --git a/libraries/EEPROM/src/EEPROM.cpp b/libraries/EEPROM/src/EEPROM.cpp index 863b2b89..f8b9b802 100644 --- a/libraries/EEPROM/src/EEPROM.cpp +++ b/libraries/EEPROM/src/EEPROM.cpp @@ -21,9 +21,9 @@ Flash is 0x00 to 0xFF000. EEPROM writes will start at 0xFF000 - 8192 = 0xF2000. Page erase takes 15ms - Writing a byte takes 30ms - Writing a float across two words takes 30ms - Update (no write) takes 1ms + Writing a byte takes 19ms + Writing a float across two words takes 19ms + Update (no write) takes ~1ms Development environment specifics: Arduino IDE 1.8.x @@ -40,270 +40,81 @@ #include "EEPROM.h" #include "Arduino.h" -//Constructor -ap3_EEPROM::ap3_EEPROM() -{ -} - -//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - //Write a byte to a given "EEPROM" location -//Automatically masks user's byte into flash without -//affecting other bytes in this flash word -void ap3_EEPROM::write(uint16_t eepromLocation, uint8_t dataToWrite) +void write(uint16_t eepromLocation, uint8_t dataToWrite) { - uint32_t flashLocation = AP3_FLASH_EEPROM_START + eepromLocation; - writeWordToFlash(flashLocation, (uint32_t)dataToWrite | 0xFFFFFF00); + writeBlockToEEPROM(eepromLocation, &dataToWrite, 1); } //Read a byte from a given location in "EEPROM" -uint8_t ap3_EEPROM::read(uint16_t eepromLocation) +uint8_t read(uint16_t eepromLocation) { uint32_t flashLocation = AP3_FLASH_EEPROM_START + eepromLocation; return (*(uint8_t *)flashLocation); } -//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - -//Get method is overloaded with the following variable types -//char, byte, int, unsigned int, long, unsigned long, float, double? - -void ap3_EEPROM::get(uint16_t eepromLocation, uint8_t &dataToGet) -{ - dataToGet = *(uint8_t *)(AP3_FLASH_EEPROM_START + eepromLocation); -} -void ap3_EEPROM::get(uint16_t eepromLocation, uint16_t &dataToGet) -{ - dataToGet = *(uint16_t *)(AP3_FLASH_EEPROM_START + eepromLocation); -} -void ap3_EEPROM::get(uint16_t eepromLocation, int16_t &dataToGet) -{ - dataToGet = *(int16_t *)(AP3_FLASH_EEPROM_START + eepromLocation); -} -void ap3_EEPROM::get(uint16_t eepromLocation, int &dataToGet) -{ - dataToGet = *(int *)(AP3_FLASH_EEPROM_START + eepromLocation); -} -void ap3_EEPROM::get(uint16_t eepromLocation, unsigned int &dataToGet) -{ - dataToGet = *(unsigned int *)(AP3_FLASH_EEPROM_START + eepromLocation); -} -void ap3_EEPROM::get(uint16_t eepromLocation, int32_t &dataToGet) -{ - dataToGet = *(int32_t *)(AP3_FLASH_EEPROM_START + eepromLocation); -} -void ap3_EEPROM::get(uint16_t eepromLocation, uint32_t &dataToGet) -{ - dataToGet = *(uint32_t *)(AP3_FLASH_EEPROM_START + eepromLocation); -} -void ap3_EEPROM::get(uint16_t eepromLocation, float &dataToGet) -{ - union { - float f; - uint32_t b; - } temp; - temp.b = *(uint32_t *)(AP3_FLASH_EEPROM_START + eepromLocation); - - dataToGet = temp.f; -} - -void ap3_EEPROM::get(uint16_t eepromLocation, double &dataToGet) -{ - union { - double lf; - uint32_t b[2]; - } temp; - temp.b[1] = *(uint32_t *)(AP3_FLASH_EEPROM_START + eepromLocation); //LSB; - temp.b[0] = *(uint32_t *)(AP3_FLASH_EEPROM_START + eepromLocation + 4); //MSB; - dataToGet = temp.lf; -} - -//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - -//Put method is overloaded with the following variable types -//char, byte, int, unsigned int, long, unsigned long, float, double? - -void ap3_EEPROM::put(uint16_t eepromLocation, uint8_t dataToWrite) -{ - writeWordToFlash((AP3_FLASH_EEPROM_START + eepromLocation), (uint32_t)dataToWrite | 0xFFFFFF00); -} -void ap3_EEPROM::put(uint16_t eepromLocation, uint16_t dataToWrite) -{ - writeWordToFlash((AP3_FLASH_EEPROM_START + eepromLocation), (uint32_t)dataToWrite | 0xFFFF0000); -} -void ap3_EEPROM::put(uint16_t eepromLocation, int16_t dataToWrite) -{ - writeWordToFlash((AP3_FLASH_EEPROM_START + eepromLocation), (uint32_t)dataToWrite | 0xFFFF0000); -} -void ap3_EEPROM::put(uint16_t eepromLocation, int dataToWrite) //ints are 32 bit on M4F -{ - writeWordToFlash((AP3_FLASH_EEPROM_START + eepromLocation), (uint32_t)dataToWrite); -} -void ap3_EEPROM::put(uint16_t eepromLocation, unsigned int dataToWrite) //ints are 32 bit on M4F -{ - writeWordToFlash((AP3_FLASH_EEPROM_START + eepromLocation), (uint32_t)dataToWrite); -} -void ap3_EEPROM::put(uint16_t eepromLocation, int32_t dataToWrite) -{ - writeWordToFlash((AP3_FLASH_EEPROM_START + eepromLocation), (int32_t)dataToWrite); -} -void ap3_EEPROM::put(uint16_t eepromLocation, uint32_t dataToWrite) -{ - writeWordToFlash((AP3_FLASH_EEPROM_START + eepromLocation), (uint32_t)dataToWrite); -} -void ap3_EEPROM::put(uint16_t eepromLocation, float dataToWrite) -{ - union { - float f; - uint32_t b; - } temp; - temp.f = dataToWrite; - - writeWordToFlash((AP3_FLASH_EEPROM_START + eepromLocation), (uint32_t)temp.b); -} - -void ap3_EEPROM::put(uint16_t eepromLocation, double dataToWrite) //64 bits -{ - union { - double lf; - uint32_t b[2]; - } temp; - temp.lf = dataToWrite; - - writeWordToFlash((AP3_FLASH_EEPROM_START + eepromLocation), (uint32_t)temp.b[1]); //LSB - writeWordToFlash((AP3_FLASH_EEPROM_START + eepromLocation + 4), (uint32_t)temp.b[0]); //MSB -} - -//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - -//The update functions simply call the put functions -//Put automatically checks to see if a spot needs updating -void ap3_EEPROM::update(uint16_t eepromLocation, uint8_t dataToWrite) -{ - put(eepromLocation, dataToWrite); -} -void ap3_EEPROM::update(uint16_t eepromLocation, uint16_t dataToWrite) -{ - put(eepromLocation, dataToWrite); -} -void ap3_EEPROM::update(uint16_t eepromLocation, int16_t dataToWrite) -{ - put(eepromLocation, dataToWrite); -} -void ap3_EEPROM::update(uint16_t eepromLocation, int dataToWrite) //ints are 32 bit on M4F -{ - put(eepromLocation, dataToWrite); -} -void ap3_EEPROM::update(uint16_t eepromLocation, unsigned int dataToWrite) //ints are 32 bit on M4F -{ - put(eepromLocation, dataToWrite); -} -void ap3_EEPROM::update(uint16_t eepromLocation, int32_t dataToWrite) -{ - put(eepromLocation, dataToWrite); -} -void ap3_EEPROM::update(uint16_t eepromLocation, uint32_t dataToWrite) -{ - put(eepromLocation, dataToWrite); -} -void ap3_EEPROM::update(uint16_t eepromLocation, float dataToWrite) -{ - put(eepromLocation, dataToWrite); -} -void ap3_EEPROM::update(uint16_t eepromLocation, double dataToWrite) //64 bits -{ - put(eepromLocation, dataToWrite); -} - -//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - -uint16_t ap3_EEPROM::length() -{ - return (AP3_FLASH_EEPROM_SIZE); -} - //Erase 8k page encapsulating the EEPROM section -void ap3_EEPROM::erase() +void EEPROMClass::erase() { am_hal_flash_page_erase(AM_HAL_FLASH_PROGRAM_KEY, AM_HAL_FLASH_ADDR2INST(AP3_FLASH_EEPROM_START), AM_HAL_FLASH_ADDR2PAGE(AP3_FLASH_EEPROM_START)); } -//This is the main helper function -//Reprogram a given location with 32-bits -//Flash is written to in words at locations that are %4=0 -//Span words if necessary //1) Make copy of current flash contents into SRAM -//2) Turn user's requested spot into 0xFFs -//3) Erase flash page (8k) -//4) Write SRAM back into flash -//5) Write user's data onto the spot with recently created 0xFFs -//Note - this code assumes EEPROM temp space is contained in one page -void ap3_EEPROM::writeWordToFlash(uint32_t flashLocation, uint32_t dataToWrite) +//2) Record user data into SRAM. +//3) Check if new data is different from flash. +//4) Erase flash page (8k) +//5) Write SRAM back into flash +void writeBlockToEEPROM(uint16_t eepromLocation, const uint8_t *dataToWrite, uint16_t blockSize) { //Error check - if (flashLocation >= AP3_FLASH_EEPROM_START + AP3_FLASH_EEPROM_SIZE) + if (eepromLocation + blockSize >= AP3_FLASH_EEPROM_SIZE) { - return; + blockSize = AP3_FLASH_EEPROM_SIZE - eepromLocation; } - if (flashLocation < AP3_FLASH_EEPROM_START) + + //Read the contents of current "EEPROM" to SRAM + //Flash is written in 32-bit words but user passes in array of bytes + //Create an array of 32-bit words but reference it a byte at a time + uint32_t flashContent[AP3_FLASH_EEPROM_SIZE / 4]; + + //We can't read 32bits at a time because the way flash is oriented (little endian) + //So we read a byte at a time + uint8_t *eepromContents = (uint8_t *)flashContent; + for (uint16_t x = 0; x < AP3_FLASH_EEPROM_SIZE; x++) { - return; + eepromContents[x] = *(uint8_t *)(AP3_FLASH_EEPROM_START + x); } - //Check to see if location needs updating - if (*(uint32_t *)(flashLocation) == dataToWrite) + //Write the caller's new data into the byte array + for (uint16_t x = 0; x < blockSize; x++) { - return; + eepromContents[eepromLocation + x] = dataToWrite[x]; } - //First we have to read the contents of current "EEPROM" to SRAM - uint32_t tempContents[AP3_FLASH_EEPROM_SIZE / 4]; - uint16_t spot = 0; - for (uint16_t x = 0; x < AP3_FLASH_EEPROM_SIZE; x += 4) + //Run a check here to see if the new data is the same as what's in flash. If it's the same, + //just return, don't erase flash. + bool theSame = true; + for (uint16_t x = 0; x < AP3_FLASH_EEPROM_SIZE; x++) { - tempContents[spot++] = *(uint32_t *)(AP3_FLASH_EEPROM_START + x); + if (eepromContents[x] != *(uint8_t *)(AP3_FLASH_EEPROM_START + x)) + { + theSame = false; + break; + } } + if (theSame == true) + return; //Then we erase an 8K page am_hal_flash_page_erase(AM_HAL_FLASH_PROGRAM_KEY, - AM_HAL_FLASH_ADDR2INST(flashLocation), - AM_HAL_FLASH_ADDR2PAGE(flashLocation)); - - //Zero out this word(s) - uint8_t byteOffset = (flashLocation % 4); - uint16_t wordLocation = (flashLocation - AP3_FLASH_EEPROM_START) / 4; - - //Mask in the new data into the array - if (byteOffset == 0) - { - //Easy - update this word with new word - tempContents[wordLocation] = dataToWrite; - } - else - { - //Clear the upper bytes of the first word to 0s - tempContents[wordLocation] &= ~(0xFFFFFFFF << (byteOffset * 8)); - - //Clear the lower bytes of the second word to 0s - tempContents[wordLocation + 1] &= ~(0xFFFFFFFF >> ((4 - byteOffset) * 8)); - - //OR in upper bytes of this word with new data - uint32_t dataToWriteFirstWord = dataToWrite << (byteOffset * 8); - - //OR in the lower bytes of the following word with new data - uint32_t dataToWriteSecondWord = dataToWrite >> ((4 - byteOffset) * 8); - - tempContents[wordLocation] |= dataToWriteFirstWord; - tempContents[wordLocation + 1] |= dataToWriteSecondWord; - } + AM_HAL_FLASH_ADDR2INST(AP3_FLASH_EEPROM_START + eepromLocation), + AM_HAL_FLASH_ADDR2PAGE(AP3_FLASH_EEPROM_START + eepromLocation)); //Then we write the contents of the array back am_hal_flash_program_main(AM_HAL_FLASH_PROGRAM_KEY, - tempContents, + flashContent, (uint32_t *)AP3_FLASH_EEPROM_START, - AP3_FLASH_EEPROM_SIZE); + AP3_FLASH_EEPROM_SIZE / 4); } - -ap3_EEPROM EEPROM; \ No newline at end of file diff --git a/libraries/EEPROM/src/EEPROM.h b/libraries/EEPROM/src/EEPROM.h index deb359d6..56890856 100644 --- a/libraries/EEPROM/src/EEPROM.h +++ b/libraries/EEPROM/src/EEPROM.h @@ -8,8 +8,6 @@ https://www.sparkfun.com/products/15411 https://www.sparkfun.com/products/15412 - Written by Nathan Seidle @ SparkFun Electronics, June 16th, 2019 - Pseudo-EEPROM on the Cortex-M4F https://github.com/sparkfun/SparkFun_Apollo3 @@ -23,20 +21,33 @@ at 0xFE000; Page erase takes 15ms - Writing a byte takes 30ms - Writing a float across two words takes 30ms - Update (no write) takes 1ms + Writing a byte takes 19ms + Writing a float across two words takes 19ms + Update (no write) takes ~1ms Development environment specifics: Arduino IDE 1.8.x - This program is distributed in the hope that it will be useful, + Original Copyright (c) 2006 David A. Mellis. All right reserved. + New version by Christopher Andrews 2015. + This copy has minor modificatons for use with Teensy, by Paul Stoffregen + This copy has minor modificatons for use with Artemis, by Nathan Seidle + + This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + EERef class. + + This object references an EEPROM cell. + Its purpose is to mimic a typical byte of RAM, however its storage is the EEPROM. + This class has an overhead of two bytes, similar to storing a pointer to an EEPROM cell. - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ #ifndef _EEPROM_H @@ -53,86 +64,139 @@ Error : EEPROM start address must be divisble by 8192 #endif -//By limiting EEPROM size to 1024, we reduce the amount of SRAM required and -//time needed to mask in individual bytes and words into flash. It can be increased -//to 8096 if needed -#define AP3_FLASH_EEPROM_SIZE 1024 + //By limiting EEPROM size to 1024 bytes, we reduce the amount of SRAM required and + //time needed to read/write words into flash. It can be increased + //to 2048 if needed + //1024 = 19ms update time + //2048 = 23ms update time + const int AP3_FLASH_EEPROM_SIZE = 1024; //In bytes - //class TwoWire : public Stream, public IOMaster{} +uint8_t read(uint16_t eepromLocation); +void write(uint16_t eepromLocation, uint8_t dataToWrite); +void writeBlockToEEPROM(uint16_t eepromLocation, const uint8_t *dataToWrite, uint16_t blockSize); - class ap3_EEPROM +struct EERef { -public: - ap3_EEPROM(); - - //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - - //8 bit - uint8_t read(uint16_t eepromLocation); - void write(uint16_t eepromLocation, uint8_t dataToWrite); - void get(uint16_t eepromLocation, uint8_t &dataToGet); - - //16 bit - void get(uint16_t eepromLocation, uint16_t &dataToGet); - void get(uint16_t eepromLocation, int16_t &dataToGet); - - //32 bit - void get(uint16_t eepromLocation, int &dataToGet); - void get(uint16_t eepromLocation, unsigned int &dataToGet); - void get(uint16_t eepromLocation, int32_t &dataToGet); - void get(uint16_t eepromLocation, uint32_t &dataToGet); - void get(uint16_t eepromLocation, float &dataToGet); - - //64 bit - void get(uint16_t eepromLocation, double &dataToGet); - - //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - - //8 bit - void put(uint16_t eepromLocation, uint8_t dataToWrite); + EERef(const int index) + : index(index) {} + + //Access/read members. + uint8_t operator*() const { return read(index); } + operator const uint8_t() const { return **this; } + + //Assignment/write members. + EERef &operator=(const EERef &ref) { return *this = *ref; } + EERef &operator=(uint8_t in) { return write(index, in), *this; } + EERef &operator+=(uint8_t in) { return *this = **this + in; } + EERef &operator-=(uint8_t in) { return *this = **this - in; } + EERef &operator*=(uint8_t in) { return *this = **this * in; } + EERef &operator/=(uint8_t in) { return *this = **this / in; } + EERef &operator^=(uint8_t in) { return *this = **this ^ in; } + EERef &operator%=(uint8_t in) { return *this = **this % in; } + EERef &operator&=(uint8_t in) { return *this = **this & in; } + EERef &operator|=(uint8_t in) { return *this = **this | in; } + EERef &operator<<=(uint8_t in) { return *this = **this << in; } + EERef &operator>>=(uint8_t in) { return *this = **this >> in; } + + EERef &update(uint8_t in) { return in != *this ? *this = in : *this; } + + /** Prefix increment/decrement **/ + EERef &operator++() { return *this += 1; } + EERef &operator--() { return *this -= 1; } + + /** Postfix increment/decrement **/ + uint8_t operator++(int) + { + uint8_t ret = **this; + return ++(*this), ret; + } + + uint8_t operator--(int) + { + uint8_t ret = **this; + return --(*this), ret; + } + + int index; //Index of current EEPROM cell. +}; - //16 bit - void put(uint16_t eepromLocation, uint16_t dataToWrite); - void put(uint16_t eepromLocation, int16_t dataToWrite); +/*** + EEPtr class. - // 32 bit - void put(uint16_t eepromLocation, int dataToWrite); - void put(uint16_t eepromLocation, unsigned int dataToWrite); - void put(uint16_t eepromLocation, int32_t dataToWrite); - void put(uint16_t eepromLocation, uint32_t dataToWrite); - void put(uint16_t eepromLocation, float dataToWrite); + This object is a bidirectional pointer to EEPROM cells represented by EERef objects. + Just like a normal pointer type, this can be dereferenced and repositioned using + increment/decrement operators. +***/ - //64 bit - void put(uint16_t eepromLocation, double dataToWrite); +struct EEPtr +{ - //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + EEPtr(const int index) + : index(index) {} - //8 bit - void update(uint16_t eepromLocation, uint8_t dataToWrite); + operator const int() const { return index; } + EEPtr &operator=(int in) { return index = in, *this; } - //16 bit - void update(uint16_t eepromLocation, uint16_t dataToWrite); - void update(uint16_t eepromLocation, int16_t dataToWrite); + //Iterator functionality. + bool operator!=(const EEPtr &ptr) { return index != ptr.index; } + EERef operator*() { return index; } - // 32 bit - void update(uint16_t eepromLocation, int dataToWrite); - void update(uint16_t eepromLocation, unsigned int dataToWrite); - void update(uint16_t eepromLocation, int32_t dataToWrite); - void update(uint16_t eepromLocation, uint32_t dataToWrite); - void update(uint16_t eepromLocation, float dataToWrite); + /** Prefix & Postfix increment/decrement **/ + EEPtr &operator++() { return ++index, *this; } + EEPtr &operator--() { return --index, *this; } + EEPtr operator++(int) { return index++; } + EEPtr operator--(int) { return index--; } - //64 bit - void update(uint16_t eepromLocation, double dataToWrite); + int index; //Index of current EEPROM cell. +}; - //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +/*** + EEPROMClass class. - uint16_t length(); - void erase(); //Erase entire EEPROM + This object represents the entire EEPROM space. + It wraps the functionality of EEPtr and EERef into a basic interface. + This class is also 100% backwards compatible with earlier Arduino core releases. +***/ -private: - void writeWordToFlash(uint32_t flashLocation, uint32_t dataToWrite); +struct EEPROMClass +{ + //Basic user access methods. + EERef operator[](const int idx) { return idx; } + uint8_t read(int idx) { return EERef(idx); } + void write(int idx, uint8_t val) { (EERef(idx)) = val; } + void update(int idx, uint8_t val) { EERef(idx).update(val); } + void erase(); + + //STL and C++11 iteration capability. + EEPtr + begin() + { + return 0x00; + } + EEPtr end() { return length(); } //Standards requires this to be the item after the last valid entry. The returned pointer is invalid. + uint16_t length() { return AP3_FLASH_EEPROM_SIZE; } + + //Functionality to 'get' and 'put' objects to and from EEPROM. + template + T &get(int idx, T &t) + { + EEPtr e = idx; + uint8_t *ptr = (uint8_t *)&t; + for (int count = sizeof(T); count; --count, ++e) + *ptr++ = *e; + return t; + } + + template + const T &put(int idx, const T &t) //Address, data + { + const uint8_t *ptr = (const uint8_t *)&t; + + writeBlockToEEPROM(idx, ptr, sizeof(T)); //Address, data, sizeOfData + + return t; + } }; -extern ap3_EEPROM EEPROM; - -#endif +static EEPROMClass EEPROM __attribute__((unused)); +#endif //_EEPROM_H