diff --git a/.github/workflows/add_issue_to_project.yml b/.github/workflows/add_issue_to_project.yml new file mode 100644 index 0000000..6b60cc3 --- /dev/null +++ b/.github/workflows/add_issue_to_project.yml @@ -0,0 +1,18 @@ +name: Add new issue to our main project + +on: + issues: + types: + - opened + +jobs: + add-to-project: + name: Add issue to project + runs-on: ubuntu-latest + steps: + - uses: actions/add-to-project@main + with: + # You can target a project in a different organization + # to the issue + project-url: https://github.com/orgs/sparkfun/projects/19 + github-token: ${{ secrets.DEFECT_ADD_TO_PROJECT }} diff --git a/README.md b/README.md index aa4ecdc..40a210a 100644 --- a/README.md +++ b/README.md @@ -7,28 +7,56 @@ SparkFun External EEPROM Arduino Library A simple-to-use I2C library for talking to any EEPROM. It uses the same template system found in the Arduino EEPROM library so you can use the same get() and put() functions. -The device-specific specs (overall size, page size, write times, etc) are auto-detected. This library works with all types and allows the various settings to be set at runtime. All read and write restrictions associated with pages are taken care of. You can access the external memory as if it was contiguous. +Various external EEPROMs have various interface specs (overall size, page size, write times, etc). This library works with all types and allows the various settings to be set at runtime. All read and write restrictions associated with pages are taken care of. You can access the external memory as if it was contiguous. -Best used with the Qwiic EEPROM: https://www.sparkfun.com/products/18355 +Once the library has been started, the memory type needs to be set, the following is an example for the [Qwiic 24xx512 EEPROM](https://www.sparkfun.com/products/18355): -This library can be installed via the Arduino Library manager. Search for **SparkFun External EEPROM**. + myMem.setMemoryType(512); + +Where *512* is the model (ie, 24LC**512**). Setting the memory type configures the memory size in bytes, the number of address bytes, and the page size in bytes. The following memory types are valid: 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1025, 2048 + +* **0** - 24xx00 / ie [24LC00](https://github.com/sparkfun/SparkFun_External_EEPROM_Arduino_Library_Docs/blob/main/24LC00%20-%20128.pdf) +* **1** - 24xx01 / ie [24LC01B](https://github.com/sparkfun/SparkFun_External_EEPROM_Arduino_Library_Docs/blob/main/24LC01%20-%201k.pdf) +* **2** - 24xx02 / ie [24LC02B](https://github.com/sparkfun/SparkFun_External_EEPROM_Arduino_Library_Docs/blob/main/24LC02%20-%202k.pdf) +* **4** - 24xx04 / ie [CAT24C04](https://github.com/sparkfun/SparkFun_External_EEPROM_Arduino_Library_Docs/blob/main/24LC04%20-%204k%20Onsemi.PDF) +* **8** - 24xx08 / ie [BR24G08](https://github.com/sparkfun/SparkFun_External_EEPROM_Arduino_Library_Docs/blob/main/24LC08%20-%208k%20Rohm.pdf) +* **16** - 24xx16 / ie [24AA16](https://github.com/sparkfun/SparkFun_External_EEPROM_Arduino_Library_Docs/blob/main/24LC16%20-%2016k.pdf) +* **32** - 24xx32 / ie [24LC32A](https://github.com/sparkfun/SparkFun_External_EEPROM_Arduino_Library_Docs/blob/main/24LC32%20-%2032k.pdf) +* **64** - 24xx64 / ie [24FC64](https://github.com/sparkfun/SparkFun_External_EEPROM_Arduino_Library_Docs/blob/main/24LC64%20-%2064k.pdf) +* **128** - 24xx128 / ie [24LC128](https://github.com/sparkfun/SparkFun_External_EEPROM_Arduino_Library_Docs/blob/main/24LC128-%20128k.pdf) +* **256** - 24xx256 / ie [24AA256](https://github.com/sparkfun/SparkFun_External_EEPROM_Arduino_Library_Docs/blob/main/24LC256%20-%20256k.pdf) +* **512** - 24xx512 / ie [24C512C](https://github.com/sparkfun/SparkFun_External_EEPROM_Arduino_Library_Docs/blob/main/24LC512%20-%20512k.pdf) +* **1025** - 24xx1025 / ie [24LC1025](https://github.com/sparkfun/SparkFun_External_EEPROM_Arduino_Library_Docs/blob/main/24LC1024%20-%201Mbit.pdf) +* **2048** - 24xx2048 / ie [AT24CM02](https://github.com/sparkfun/SparkFun_External_EEPROM_Arduino_Library_Docs/blob/main/24LC2048%20-%202Mbit.pdf) -The method for autodetection is as follows. The original data on the EEPROM is maintained once autodetection is complete: +For a list of all the EEPROM datasheets, please see [this repo](https://github.com/sparkfun/SparkFun_External_EEPROM_Arduino_Library_Docs). We don't want to store the PDFs in the library repo, otherwise, every user will have to download all the PDFs just to install the library. -* Address Bytes: Smaller EEPROMs use one address byte and larger EEPROMs use 2 address bytes. The auto-detection routine attempts to read a byte and then write a new byte. If the read/write fails, the address byte count is increased and a write attempt is tried again. Once the correct number of address bytes is detected, the original value is written back to EEPROM. +Alternatively, the individual settings can be set. If setMemorySizeBytes/setAddressBytes/setPageSizeBytes() are called, they will overwrite any previous settings set by `setMemoryType()`. -* Page Size: 256 bytes of EEPROM are read individually (to avoid page reads). Then, new bytes are generated that are random *and* different from the original data. The new bytes are written to EEPROM in increasing page size tests (8 bytes, then 16, etc) until the data does not match. Then the original data is written back to the EEPROM. Note: The page size may be reported as 32 bytes when the actual page size is larger. This is because of the size of the I2C buffer available on your microcontroller's Arduino core's Wire implementation. On some platforms (such as Arduino Uno) the I2C write buffer is 32 bytes. Once the two write bytes are removed, that leaves only 30 bytes available for sequential reads/writes. For maximum write speeds, use a platform that has a larger buffer than the page size of the EEPROM you are using. + myMem.setMemorySizeBytes(65536); + myMem.setAddressBytes(2); // Set address bytes and page size after MemorySizeBytes() + myMem.setPageSizeBytes(128); -* Memory Size: Once address bytes and page size are determined, single bytes are read, then written, then checked at the end of the potential EEPROM space. For example, byte 65535 is read for its original value and stored. Then a new, different value is written to location 65535. If the read/write fails, we know the EEPROM is one size down (32768 bytes, aka 24XX256). +Set the memory type, or set the memory settings, but not both. -* Page write time: This setting is not detected at begin(). All EEPROMs have a max write time of 5ms. Testing with a logic analyzer has shown that all EEPROMs respect this max and have an average of ~4.5ms for a page write. Attempting to trim the page write time lower than 5ms is much less worthwhile than using up a properly sized page size setting with an adequately sized I2C write buffer. In other words, read and write as many bytes as the page size can handle, don't worry about setting the page write time to 4ms or 5ms. Note: The 24XXM02 has a 10ms max page write time. +This library is best used with the [Qwiic EEPROM](https://www.sparkfun.com/products/18355). + +This library can be installed via the Arduino Library manager. Search for **SparkFun External EEPROM**. Want to help? Please do! We are always looking for ways to improve and build out features of this library. Thanks to: -* Hutch67 for correcting the [test for pollForWriteComplete setting](https://github.com/sparkfun/SparkFun_External_EEPROM_Arduino_Library/pull/4/files) -* [TinaJ_kay](https://github.com/TylerBird) for correcting [ambiguous int declaration](https://github.com/sparkfun/SparkFun_External_EEPROM_Arduino_Library/pull/7) and adding STM32 support +* [Hutch67](https://github.com/Hutch67) for correcting the [test for pollForWriteComplete setting](https://github.com/sparkfun/SparkFun_External_EEPROM_Arduino_Library/pull/4/files) +* [TylerBird](https://github.com/TylerBird) for correcting [ambiguous int declaration](https://github.com/sparkfun/SparkFun_External_EEPROM_Arduino_Library/pull/7) and adding STM32 support +* [quarcko](https://github.com/quarcko) for [small EEPROM support](https://github.com/sparkfun/SparkFun_External_EEPROM_Arduino_Library/pull/11) (24LC02). +* [robsonos](https://github.com/robsonos) adding for [nRF52 support](https://github.com/sparkfun/SparkFun_External_EEPROM_Arduino_Library/pull/12). +* [RayNieport](https://github.com/RayNieport) for adding [RP2040 support](https://github.com/sparkfun/SparkFun_External_EEPROM_Arduino_Library/pull/14). +* [wolfbert](https://github.com/wolfbert) for adding [ESP8266 support](https://github.com/sparkfun/SparkFun_External_EEPROM_Arduino_Library/pull/15). +* [romain145](https://github.com/romain145) for fixing a [multi-page write](https://github.com/sparkfun/SparkFun_External_EEPROM_Arduino_Library/pull/18) bug. +* [wollewald](https://github.com/wollewald) for [read/write strings](https://github.com/sparkfun/SparkFun_External_EEPROM_Arduino_Library/pull/21). +* [giminotron5](https://github.com/giminotron5) for adding [write protect control](https://github.com/sparkfun/SparkFun_External_EEPROM_Arduino_Library/pull/30). +* [merlinz01](https://github.com/merlinz01) for adding [putChanged()](https://github.com/sparkfun/SparkFun_External_EEPROM_Arduino_Library/pull/38) method Repository Contents ------------------- diff --git a/examples/Example1_BasicReadWrite/Example1_BasicReadWrite.ino b/examples/Example1_BasicReadWrite/Example1_BasicReadWrite.ino index 1a6f952..d468731 100644 --- a/examples/Example1_BasicReadWrite/Example1_BasicReadWrite.ino +++ b/examples/Example1_BasicReadWrite/Example1_BasicReadWrite.ino @@ -6,7 +6,7 @@ License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license). Feel like supporting our work? Buy a board from SparkFun! - https://www.sparkfun.com/products/14764 + https://www.sparkfun.com/products/18355 This example demonstrates how to read and write various variables to memory. @@ -27,10 +27,13 @@ ExternalEEPROM myMem; void setup() { Serial.begin(115200); + //delay(250); //Often needed for ESP based platforms Serial.println("Qwiic EEPROM example"); Wire.begin(); + //We must set the memory specs. Pick your EEPROM From the list: + // 24xx00 - 128 bit / 16 bytes - 1 address byte, 1 byte page // 24xx01 - 1024 bit / 128 bytes - 1 address byte, 8 byte page // 24xx02 - 2048 bit / 256 bytes - 1 address byte, 8 byte page @@ -42,50 +45,24 @@ void setup() // 24xx128 - 131072 bit / 16384 bytes - 2 address bytes, 64 byte page // 24xx256 - 262144 bit / 32768 bytes - 2 address bytes, 64 byte page // 24xx512 - 524288 bit / 65536 bytes - 2 address bytes, 128 byte page - // 24xx1024 - 1024000 bit / 128000 byte - 2 address byte, 128 byte page + // 24xx1025 - 1024000 bit / 128000 byte - 2 address byte, 128 byte page // 24xxM02 - 2097152 bit / 262144 byte - 2 address bytes, 256 byte page - // 24xx16 - 16384 bit / 2048 bytes - 1 address byte, 16 byte page size - //myMem.setAddressBytes(1); - //myMem.setPageSizeBytes(16); - //myMem.setMemorySizeBytes(2048); - - // 24xx04 - 4096 bit / 512 bytes - 1 address byte, 16 byte page - //myMem.setAddressBytes(1); - //myMem.setPageSizeBytes(16); - //myMem.setMemorySizeBytes(2048); + // Setting the memory type configures the memory size in bytes, the number of address bytes, and the page size in bytes. - // 24xx02 - 2048 bit / 256 bytes - 1 address byte, 8 byte page - myMem.setAddressBytes(1); - myMem.setPageSizeBytes(8); - myMem.setMemorySizeBytes(256); + // Default to the Qwiic 24xx512 EEPROM: https://www.sparkfun.com/products/18355 + myMem.setMemoryType(512); // Valid types: 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1025, 2048 if (myMem.begin() == false) { Serial.println("No memory detected. Freezing."); - while (1) + while (true) ; } Serial.println("Memory detected!"); - uint32_t eepromSizeBytes = myMem.getMemorySizeBytes(); - Serial.print("Detected EEPROM size (bytes): "); - Serial.print(eepromSizeBytes); - Serial.print(" - EEPROM Type: 24XX"); - if (eepromSizeBytes == 16) - Serial.print("00"); - else - { - if ((eepromSizeBytes * 8 / 1024) < 10) Serial.print("0"); - Serial.print(eepromSizeBytes * 8 / 1024); - } - Serial.println(); - - Serial.print("Detected number of address bytes: "); - Serial.println(myMem.getAddressBytes()); - - Serial.print("Detected pageSizeBytes: "); - Serial.println(myMem.getPageSizeBytes()); + Serial.print("Mem size in bytes: "); + Serial.println(myMem.length()); //Yes you can read and write bytes, but you shouldn't! byte myValue1 = 200; diff --git a/examples/Example4_AdvancedI2C/Example4_AdvancedI2C.ino b/examples/Example2_AdvancedI2C/Example2_AdvancedI2C.ino similarity index 80% rename from examples/Example4_AdvancedI2C/Example4_AdvancedI2C.ino rename to examples/Example2_AdvancedI2C/Example2_AdvancedI2C.ino index 5327bac..51aedc1 100644 --- a/examples/Example4_AdvancedI2C/Example4_AdvancedI2C.ino +++ b/examples/Example2_AdvancedI2C/Example2_AdvancedI2C.ino @@ -6,14 +6,14 @@ License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license). Feel like supporting our work? Buy a board from SparkFun! - https://www.sparkfun.com/products/14764 + https://www.sparkfun.com/products/18355 This example demonstrates how to pass a custom EEPROM address and Wire. This library supports EEPROMs with any I2C address and any Wire hardware (Wire1, Wire2, etc) by passing them into begin. - For this example the I2C EEPROM should have all its ADR0 to VCC, + For this example, the I2C EEPROM should have all its ADR0 to VCC, ADR1 to GND, and ADR2 to GND. Hardware Connections: @@ -36,19 +36,23 @@ ExternalEEPROM myMem; void setup() { Serial.begin(115200); - delay(10); - Serial.println("I2C EEPROM example"); + //delay(250); //Often needed for ESP based platforms + Serial.println("Qwiic EEPROM example"); // Wire1.setClock(400000); //set I2C communication to 400kHz Wire1.begin(); + // Default to the Qwiic 24xx512 EEPROM: https://www.sparkfun.com/products/18355 + myMem.setMemoryType(512); // Valid types: 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1025, 2048 + #define EEPROM_ADDRESS 0b1010001 //0b1010(A2 A1 A0): A standard I2C EEPROM with the ADR0 bit set to VCC - + //Connect to a EEPROM with ADR0 set to VCC and use the Wire1 hardware to talk to the EEPROM if (myMem.begin(EEPROM_ADDRESS, Wire1) == false) //And Uno will fail to compile here { Serial.println("No memory detected. Freezing."); - while (1); + while (true) + ; } Serial.println("Memory detected!"); diff --git a/examples/Example3_ManualSettings/Example3_ManualSettings.ino b/examples/Example3_ManualSettings/Example3_ManualSettings.ino deleted file mode 100644 index d5b4195..0000000 --- a/examples/Example3_ManualSettings/Example3_ManualSettings.ino +++ /dev/null @@ -1,70 +0,0 @@ -/* - Set manual specs of an external I2C EEPROM - By: Nathan Seidle - SparkFun Electronics - Date: December 11th, 2019 - License: This code is public domain but you buy me a beer if you use this - and we meet someday (Beerware license). - Feel like supporting our work? Buy a board from SparkFun! - https://www.sparkfun.com/products/14764 - - This example demonstrates how to set the various settings for a given EEPROM. - Read the datasheet! Each EEPROM will have specific values for: - Overall EEPROM size in bytes (512kbit = 65536, 256kbit = 32768). - Bytes per page write (1, 8, 16, 32, 64, and 128 are common). - Whether write polling is supported. - Note: This will overwrite the auto-detected specs. It is recommended to use example 2 - to detect the device's settings then you can set them before - - The I2C EEPROM should have all its ADR pins set to GND (0). This is default - on the Qwiic board. - - Hardware Connections: - Plug the SparkFun Qwiic EEPROM to an Uno, Artemis, or other Qwiic equipped board - Load this sketch - Open output window at 115200bps -*/ - -#include - -#include "SparkFun_External_EEPROM.h" // Click here to get the library: http://librarymanager/All#SparkFun_External_EEPROM -ExternalEEPROM myMem; - -void setup() -{ - Serial.begin(115200); - delay(10); - Serial.println("I2C EEPROM example"); - - Wire.begin(); - Wire.setClock(400000); //Most EEPROMs can run 400kHz and higher - - if (myMem.begin() == false) - { - Serial.println("No memory detected. Freezing."); - while (1); - } - Serial.println("Memory detected!"); - - //Set settings for this EEPROM - myMem.setMemorySizeBytes(512 * 1024 / 8); //In bytes. 512kbit = 64kbyte - myMem.setPageSizeBytes(128); //In bytes. Has 128 byte page size. - myMem.enablePollForWriteComplete(); //Supports I2C polling of write completion - myMem.setPageWriteTimeMs(5); //5 ms max write time - - Serial.print("Mem size in bytes: "); - Serial.println(myMem.length()); - - float myValue3 = -7.35; - myMem.put(20, myValue3); //(location, data) - float myRead3; - myMem.get(20, myRead3); //location to read, thing to put data into - Serial.print("I read (should be -7.35): "); - Serial.println(myRead3); - -} - -void loop() -{ - -} diff --git a/examples/Example5_UserOptions/Example5_UserOptions.ino b/examples/Example3_SettingsStruc/Example3_SettingsStruc.ino similarity index 94% rename from examples/Example5_UserOptions/Example5_UserOptions.ino rename to examples/Example3_SettingsStruc/Example3_SettingsStruc.ino index aa38013..c53f76e 100644 --- a/examples/Example5_UserOptions/Example5_UserOptions.ino +++ b/examples/Example3_SettingsStruc/Example3_SettingsStruc.ino @@ -6,7 +6,7 @@ License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license). Feel like supporting our work? Buy a board from SparkFun! - https://www.sparkfun.com/products/14764 + https://www.sparkfun.com/products/18355 This example demonstrates how to record various user settings easily to EEPROM. @@ -45,15 +45,18 @@ struct_userSettings settings = { void setup() { Serial.begin(115200); - delay(10); + //delay(250); //Often needed for ESP based platforms Serial.println(F("Qwiic EEPROM example")); Wire.begin(); + // Default to the Qwiic 24xx512 EEPROM: https://www.sparkfun.com/products/18355 + myMem.setMemoryType(512); // Valid types: 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1025, 2048 + if (myMem.begin() == false) { Serial.println(F("No memory detected. Freezing.")); - while (1); + while (true); } Serial.println(F("Memory detected!")); diff --git a/examples/Example2_DetectSettings/Example2_DetectSettings.ino b/examples/Example4_DetectSettings/Example4_DetectSettings.ino similarity index 74% rename from examples/Example2_DetectSettings/Example2_DetectSettings.ino rename to examples/Example4_DetectSettings/Example4_DetectSettings.ino index f63114d..a2b3f26 100644 --- a/examples/Example2_DetectSettings/Example2_DetectSettings.ino +++ b/examples/Example4_DetectSettings/Example4_DetectSettings.ino @@ -5,8 +5,7 @@ License: Lemonadeware. Buy me a lemonade (or other) someday. This sketch demonstrates how to detect memory size, address bytes, - page size, and write time. You can also pre-assign these specs to avoid - the start up delay caused by the detection routines. + page size, and write time. Known/compatible memory types (basically all I2C EEPROMs): 24xx00 - 128 bit / 16 bytes - 1 address byte, 1 byte page size @@ -20,7 +19,7 @@ 24xx128 - 131072 bit / 16384 bytes - 2 address bytes, 64 byte page size 24xx256 - 262144 bit / 32768 bytes - 2 address bytes, 64 byte page size 24xx512 - 524288 bit / 65536 bytes - 2 address bytes, 128 byte page size - 24xx1024 - 1024000 bit / 128000 byte - 2 address bytes, 128 byte page size + 24xx1025 - 1024000 bit / 128000 byte - 2 address bytes, 128 byte page size 24xxM02 - 2097152 bit / 262144 byte - 2 address bytes, 256 byte page size */ @@ -36,13 +35,9 @@ void setup() Wire.begin(); - //The memory specs can be set before begin() to skip the auto-detection delay and write wear - //24LC16 - 16384 bit / 2048 bytes - 1 address byte, 16 byte page size - //myMem.setAddressBytes(1); - //myMem.setPageSizeBytes(16); - //myMem.setMemorySizeBytes(2048); + //We don't need to specify the memory specs before begin(). We're just looking + //for a I2C device to ACK. - //If specs are not available at begin(), they are auto-detected if (myMem.begin() == false) { Serial.println("No memory detected. Freezing."); @@ -51,20 +46,19 @@ void setup() } Serial.println("Memory detected!"); - //Detection functions can also be called/re-run after begin() Serial.print("Detected number of address bytes: "); Serial.println(myMem.detectAddressBytes()); - //Page size detection is limited by the platform. For example, the Uno has a I2C buffer - //that is 32 bytes. Therefor, page sizes above 16 bytes cannot be detected or used. For maximum + //Page size detection is limited by the platform. For example, the Uno has an I2C buffer + //that is 32 bytes. Therefore, page sizes above 16 bytes cannot be detected or used. For maximum //write speeds to an EEPROM, use a platform with a large I2C buffer (ie ESP32 is 128 bytes) //and an EEPROM with a large page size (24XX512 is 128 bytes). Serial.print("Detected pageSizeBytes: "); Serial.println(myMem.detectPageSizeBytes()); - //detectWriteTimeMs is *not* automatically called at begin() and is - //generally not needed. Write times are guaranteed to be under 5ms, - //and we use polling by default so its use is limited. + //The EEPROM write time is 5 ms for all EEPROMs currently manufactured. + //Automatically detecting the write time is therefore not generally needed, + //but it's here if needed. Serial.print("Detected page write time (ms): "); Serial.println(myMem.detectWriteTimeMs()); diff --git a/examples/Example5_CustomSettings/Example5_CustomSettings.ino b/examples/Example5_CustomSettings/Example5_CustomSettings.ino new file mode 100644 index 0000000..5c86e96 --- /dev/null +++ b/examples/Example5_CustomSettings/Example5_CustomSettings.ino @@ -0,0 +1,92 @@ +/* + Explicitly tell the library the size of the EEPROM, page size, and address bytes + Author: Nathan Seidle + Created: June 23, 2023 + License: Lemonadeware. Buy me a lemonade (or other) someday. + + This sketch demonstrates how to detect memory size, address bytes, + page size, and write time. You can also pre-assign these specs to avoid + the start up delay caused by the detection routines. + + Known/compatible memory types (basically all I2C EEPROMs): + 24xx00 - 128 bit / 16 bytes - 1 address byte, 1 byte page size + 24xx01 - 1024 bit / 128 bytes - 1 address byte, 8 byte page size + 24xx02 - 2048 bit / 256 bytes - 1 address byte, 8 byte page size + 24xx04 - 4096 bit / 512 bytes - 1 address byte, 16 byte page size + 24xx08 - 8192 bit / 1024 bytes - 1 address byte, 16 byte page size + 24xx16 - 16384 bit / 2048 bytes - 1 address byte, 16 byte page size + 24xx32 - 32768 bit / 4096 bytes - 2 address bytes, 32 byte page size + 24xx64 - 65536 bit / 8192 bytes - 2 address bytes, 32 byte page size + 24xx128 - 131072 bit / 16384 bytes - 2 address bytes, 64 byte page size + 24xx256 - 262144 bit / 32768 bytes - 2 address bytes, 64 byte page size + 24xx512 - 524288 bit / 65536 bytes - 2 address bytes, 128 byte page size + 24xx1025 - 1024000 bit / 128000 byte - 2 address bytes, 128 byte page size + 24xxM02 - 2097152 bit / 262144 byte - 2 address bytes, 256 byte page size +*/ + +#include + +#include "SparkFun_External_EEPROM.h" // Click here to get the library: http://librarymanager/All#SparkFun_External_EEPROM +ExternalEEPROM myMem; + +void setup() +{ + Serial.begin(115200); + Serial.println("Qwiic EEPROM example"); + + Wire.begin(); + + //Explicitly set the address bytes, page size, and memory size for this EEPROM + // 24xx512 - 524288 bit / 65536 bytes - 2 address bytes, 128 byte page + myMem.setMemorySizeBytes(65536); //This function will set the AddressBytes and PageSize. + myMem.setAddressBytes(2); //Call these functions after MemorySizeBytes. Only needed if you have a very unique EEPROM with odd Address Bytes and Page Sizes. + myMem.setPageSizeBytes(128); + + if (myMem.begin() == false) + { + Serial.println("No memory detected. Freezing."); + while (1) + ; + } + Serial.println("Memory detected!"); + + Serial.print("Mem size in bytes: "); + Serial.println(myMem.length()); + + //Yes you can read and write bytes, but you shouldn't! + byte myValue1 = 200; + myMem.write(0, myValue1); //(location, data) + + byte myRead1 = myMem.read(0); + Serial.print("I read (should be 200): "); + Serial.println(myRead1); + + //You should use gets and puts. This will automatically and correctly arrange + //the bytes for larger variable types. + int myValue2 = -366; + myMem.put(10, myValue2); //(location, data) + int myRead2; + myMem.get(10, myRead2); //location to read, thing to put data into + Serial.print("I read (should be -366): "); + Serial.println(myRead2); + + float myValue3 = -7.35; + myMem.put(20, myValue3); //(location, data) + float myRead3; + myMem.get(20, myRead3); //location to read, thing to put data into + Serial.print("I read (should be -7.35): "); + Serial.println(myRead3); + + String myString = "Hi, I am just a simple test string"; + unsigned long nextEEPROMLocation = myMem.putString(30, myString); + String myRead4 = ""; + myMem.getString(30, myRead4); + Serial.print("I read: "); + Serial.println(myRead4); + Serial.print("Next available EEPROM location: "); + Serial.println(nextEEPROMLocation); +} + +void loop() +{ +} \ No newline at end of file diff --git a/examples/Example6_InterfaceTest/Example6_InterfaceTest.ino b/examples/Example6_InterfaceTest/Example6_InterfaceTest.ino deleted file mode 100644 index 8c1d0f2..0000000 --- a/examples/Example6_InterfaceTest/Example6_InterfaceTest.ino +++ /dev/null @@ -1,470 +0,0 @@ -/* - Read and write settings and calibration data to an external I2C EEPROM - By: Nathan Seidle - SparkFun Electronics - Date: December 11th, 2019 - License: This code is public domain but you buy me a beer if you use this - and we meet someday (Beerware license). - Feel like supporting our work? Buy a board from SparkFun! - https://www.sparkfun.com/products/14764 - - This example demonstrates how to read and write various variables to memory. - - The I2C EEPROM should have all its ADR pins set to GND (0). This is default - on the Qwiic board. - - Hardware Connections: - Plug the SparkFun Qwiic EEPROM to an Uno, Artemis, or other Qwiic equipped board - Load this sketch - Open output window at 115200bps -*/ - -#include - -#include "SparkFun_External_EEPROM.h" // Click here to get the library: http://librarymanager/All#SparkFun_External_EEPROM -ExternalEEPROM myMem; - -void setup() -{ - Serial.begin(115200); - delay(10); - Serial.println("I2C EEPROM example"); - - //Pick any unconnected analog pin - randomSeed(analogRead(A0)); - //randomSeed(analogRead(A15)); - - unsigned int randomLocation; - - Wire.begin(); - Wire.setClock(400000); - //Wire.setClock(1000000); - - //The memory specs can be set before begin() to skip the auto-detection delay and write wear - //24XX04 - 4096 bit / 512 bytes - 1 address byte, 16 byte page size - myMem.setAddressBytes(1); - myMem.setPageSizeBytes(16); - myMem.setMemorySizeBytes(512); - - - if (myMem.begin() == false) - { - Serial.println("No memory detected. Freezing."); - while (1) - ; - } - Serial.println("Memory detected!"); - - uint32_t eepromSizeBytes = myMem.getMemorySizeBytes(); - Serial.print("Detected EEPROM type: 24XX"); - if (eepromSizeBytes == 16) - Serial.print("00"); - else - { - if ((eepromSizeBytes * 8 / 1024) < 10) Serial.print("0"); - Serial.print(eepromSizeBytes * 8 / 1024); - } - Serial.print(" - bytes: "); - Serial.print(eepromSizeBytes); - Serial.println(); - - // Serial.print("Detected number of address bytes: "); - // Serial.println(myMem.getAddressBytes()); - // - // Serial.print("Detected pageSizeBytes: "); - // Serial.println(myMem.getPageSizeBytes()); - // - - bool allTestsPassed = true; - - //Erase test - //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - long startTime = millis(); - myMem.erase(); - long endTime = millis(); - Serial.print("Time to erase all EEPROM: "); - Serial.print(endTime - startTime); - Serial.println("ms"); - //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - - //Byte sequential test - //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - Serial.println(""); - Serial.println("8 bit tests"); - byte myValue1 = 200; - byte myValue2 = 23; - randomLocation = random(0, myMem.length() - (sizeof(byte) * 2)); - - startTime = micros(); - myMem.write(randomLocation, myValue1); //(location, data) - while (myMem.isConnected() == false); //Wait for write to complete - endTime = micros(); - Serial.print("Time to record byte: "); - Serial.print(endTime - startTime); - Serial.println(" us"); - - myMem.put(randomLocation + sizeof(byte), myValue2); - while (myMem.isConnected() == false); //Wait for write to complete - - startTime = micros(); - myMem.write(randomLocation, myValue1); //(location, data) - while (myMem.isConnected() == false); //Wait for write to complete - endTime = micros(); - Serial.print("Time to write identical byte to same location (should be ~0ms): "); - Serial.print(endTime - startTime); - Serial.println(" us"); - - startTime = micros(); - byte response1 = myMem.read(randomLocation); - endTime = micros(); - Serial.print("Time to read byte: "); - Serial.print(endTime - startTime); - Serial.println(" us"); - -while(1); - - byte response2 = myMem.read(randomLocation + sizeof(byte)); - Serial.print("Location "); - Serial.print(randomLocation); - Serial.print(" should be "); - Serial.print(myValue1); - Serial.print(": "); - Serial.println(response1); - - Serial.print("Location "); - Serial.print(randomLocation + sizeof(byte)); - Serial.print(" should be "); - Serial.print(myValue2); - Serial.print(": "); - Serial.println(response2); - if (myValue1 != response1) - allTestsPassed = false; - if (myValue2 != response2) - allTestsPassed = false; - //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - - Serial.println(""); - Serial.println("16 bit tests"); - - //int16_t and uint16_t tests - //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - uint16_t myValue3 = 3411; - int16_t myValue4 = -366; - randomLocation = random(0, myMem.length() - (sizeof(int16_t) * 2)); - - startTime = micros(); - myMem.put(randomLocation, myValue3); - endTime = micros(); - Serial.print("Time to record int16: "); - Serial.print(endTime - startTime); - Serial.println(" us"); - - myMem.put(randomLocation + sizeof(int16_t), myValue4); - - uint16_t response3; - int16_t response4; - - startTime = micros(); - myMem.get(randomLocation, response3); - endTime = micros(); - Serial.print("Time to read int16: "); - Serial.print(endTime - startTime); - Serial.println(" us"); - - myMem.get(randomLocation + sizeof(int16_t), response4); - Serial.print("Location "); - Serial.print(randomLocation); - Serial.print(" should be "); - Serial.print(myValue3); - Serial.print(": "); - Serial.println(response3); - - Serial.print("Location "); - Serial.print(randomLocation + sizeof(int16_t)); - Serial.print(" should be "); - Serial.print(myValue4); - Serial.print(": "); - Serial.println(response4); - - if (myValue3 != response3) - allTestsPassed = false; - if (myValue4 != response4) - allTestsPassed = false; - //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - - Serial.println(""); - Serial.println("int tests"); - - //int and unsigned int tests - //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - Serial.print("Size of int: "); - Serial.println(sizeof(int)); //Uno reports this as 2 - int myValue5 = -2450; - unsigned int myValue6 = 4001; - randomLocation = random(0, myMem.length() - (sizeof(int) * 2)); - - startTime = micros(); - myMem.put(randomLocation, myValue5); - endTime = micros(); - Serial.print("Time to record int: "); - Serial.print(endTime - startTime); - Serial.println(" us"); - myMem.put(randomLocation + sizeof(int), myValue6); - - int response5; - unsigned int response6; - - startTime = micros(); - myMem.get(randomLocation, response5); - endTime = micros(); - Serial.print("Time to read int: "); - Serial.print(endTime - startTime); - Serial.println(" us"); - - myMem.get(randomLocation + sizeof(int), response6); - Serial.print("Location "); - Serial.print(randomLocation); - Serial.print(" should be "); - Serial.print(myValue5); - Serial.print(": "); - Serial.println(response5); - - Serial.print("Location "); - Serial.print(randomLocation + sizeof(int)); - Serial.print(" should be "); - Serial.print(myValue6); - Serial.print(": "); - Serial.println(response6); - if (myValue5 != response5) - allTestsPassed = false; - if (myValue6 != response6) - allTestsPassed = false; - //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - - Serial.println(""); - Serial.println("32 bit tests"); - - //int32_t and uint32_t sequential test - //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - int32_t myValue7 = -341002; - uint32_t myValue8 = 241544; - randomLocation = random(0, myMem.length() - (sizeof(int32_t) * 2)); - - myMem.put(randomLocation, myValue7); - myMem.put(randomLocation + sizeof(int32_t), myValue8); - - int32_t response7; - uint32_t response8; - - startTime = micros(); - myMem.get(randomLocation, response7); - endTime = micros(); - Serial.print("Time to read int32: "); - Serial.print(endTime - startTime); - Serial.println(" us"); - - myMem.get(randomLocation + sizeof(int32_t), response8); - Serial.print("Location "); - Serial.print(randomLocation); - Serial.print(" should be "); - Serial.print(myValue7); - Serial.print(": "); - Serial.println(response7); - - Serial.print("Location "); - Serial.print(randomLocation + sizeof(int32_t)); - Serial.print(" should be "); - Serial.print(myValue8); - Serial.print(": "); - Serial.println(response8); - if (myValue7 != response7) - allTestsPassed = false; - if (myValue8 != response8) - allTestsPassed = false; - //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - - //float (32) sequential test - //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - Serial.print("Size of float: "); - Serial.println(sizeof(float)); - float myValue9 = -7.35; - float myValue10 = 5.22; - randomLocation = random(0, myMem.length() - (sizeof(float) * 2) ); - - myMem.put(randomLocation, myValue9); - myMem.put(randomLocation + sizeof(float), myValue10); - - float response9; - float response10; - - startTime = micros(); - myMem.get(randomLocation, response9); - endTime = micros(); - Serial.print("Time to read float: "); - Serial.print(endTime - startTime); - Serial.println(" us"); - - myMem.get(randomLocation + sizeof(float), response10); - Serial.print("Location "); - Serial.print(randomLocation); - Serial.print(" should be "); - Serial.print(myValue9); - Serial.print(": "); - Serial.println(response9); - - Serial.print("Location "); - Serial.print(randomLocation + sizeof(float)); - Serial.print(" should be "); - Serial.print(myValue10); - Serial.print(": "); - Serial.println(response10); - - if (myValue9 != response9) - allTestsPassed = false; - if (myValue10 != response10) - allTestsPassed = false; - //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - - Serial.println(""); - Serial.println("64 bit tests"); - - //double (64) sequential test - //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - Serial.print("Size of double: "); - Serial.println(sizeof(double)); - double myValue11 = -290.3485723409857; - double myValue12 = 384.957; //34987; - double myValue13 = 917.14159; - double myValue14 = 254.8877; - randomLocation = random(0, myMem.length() - (sizeof(double) * 2)); - - startTime = micros(); - myMem.put(randomLocation, myValue11); - endTime = micros(); - Serial.print("Time to record 64-bits: "); - Serial.print(endTime - startTime); - Serial.println(" us"); - - myMem.put(randomLocation + sizeof(double), myValue12); - myMem.put(myMem.length() - sizeof(double), myValue13); //Test end of EEPROM space - - double response11; - double response12; - double response13; - - startTime = micros(); - myMem.get(randomLocation, response11); - endTime = micros(); - Serial.print("Time to read 64-bits: "); - Serial.print(endTime - startTime); - Serial.println(" us"); - - myMem.get(randomLocation + sizeof(double), response12); - myMem.get(myMem.length() - sizeof(double), response13); - Serial.print("Location "); - Serial.print(randomLocation); - Serial.print(" should be "); - Serial.print(myValue11); - Serial.print(": "); - Serial.println(response11); - - Serial.print("Location "); - Serial.print(randomLocation + sizeof(double)); - Serial.print(" should be "); - Serial.print(myValue12); - Serial.print(": "); - Serial.println(response12); - - Serial.print("Edge of EEPROM "); - Serial.print(myMem.length() - sizeof(double)); - Serial.print(" should be "); - Serial.print(myValue13); - Serial.print(": "); - Serial.println(response13); - - double response14; - myMem.put(myMem.length() - sizeof(double), myValue14); //Test the re-write of a spot - myMem.get(myMem.length() - sizeof(double), response14); - Serial.print("Rewrite of "); - Serial.print(myMem.length() - sizeof(double)); - Serial.print(" should be "); - Serial.print(myValue14); - Serial.print(": "); - Serial.println(response14); - - if (myValue11 != response11) - allTestsPassed = false; - if (myValue12 != response12) - allTestsPassed = false; - if (myValue13 != response13) - allTestsPassed = false; - if (myValue14 != response14) - allTestsPassed = false; - //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - - Serial.println(""); - Serial.println("Buffer Write Test"); - - //Buffer write test - //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - //char myChars[242] = "Lorem ipsum dolor sit amet, has in verterem accusamus. Nulla viderer inciderint eum at. Quo elit nullam malorum te, agam fuisset detracto an sea, eam ut liber aperiri. Id qui velit facilisi. Mel probatus definitionem id, eu amet vidisse eum."; - char myChars[88] = "Lorem ipsum dolor sit amet, has in verterem accusamus. Nulla viderer inciderint eum at."; - randomLocation = random(0, myMem.length() - sizeof(myChars)); - - Serial.print("Calculated time to record array of "); - Serial.print(sizeof(myChars)); - Serial.print(" characters: ~"); - Serial.print((uint32_t)sizeof(myChars) / myMem.getPageSizeBytes() * myMem.getWriteTimeMs()); - Serial.println("ms"); - - startTime = micros(); - myMem.put(randomLocation, myChars); - endTime = micros(); - Serial.print("Time to record array: "); - Serial.print(endTime - startTime); - Serial.println(" us"); - - char readMy[sizeof(myChars)]; - - startTime = micros(); - myMem.get(randomLocation, readMy); - endTime = micros(); - Serial.print("Time to read array: "); - Serial.print(endTime - startTime); - Serial.println(" us"); - - // Serial.print("Location "); - // Serial.print(randomLocation); - // Serial.print(" string should read:"); - // Serial.println(myChars); - // Serial.println(readMy); - if (strcmp(myChars, readMy) != 0) - { - Serial.println("String compare failed"); - allTestsPassed = false; - } - - //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - - Serial.println(); - Serial.print("Memory Contents:"); - for (uint16_t x = 0; x < 32 * 4; x++) - { - if (x % 16 == 0) - Serial.println(); - Serial.print(" 0x"); - if (myMem.read(x) < 0x10) - Serial.print("0"); - Serial.print(myMem.read(x), HEX); - } - Serial.println(); - - if (allTestsPassed == true) - Serial.println("All tests PASSED!"); - else - Serial.println("Something went wrong. See output."); -} - -void loop() -{ -} \ No newline at end of file diff --git a/examples/Example7_UniversalProgrammer/Example7_UniversalProgrammer.ino b/examples/Example6_UniversalProgrammer/Example6_UniversalProgrammer.ino similarity index 98% rename from examples/Example7_UniversalProgrammer/Example7_UniversalProgrammer.ino rename to examples/Example6_UniversalProgrammer/Example6_UniversalProgrammer.ino index 47ae204..d6c8f89 100644 --- a/examples/Example7_UniversalProgrammer/Example7_UniversalProgrammer.ino +++ b/examples/Example6_UniversalProgrammer/Example6_UniversalProgrammer.ino @@ -71,9 +71,7 @@ void setup() beginSD(); //Set settings for a 24LC1025 - myMem.setMemorySizeBytes(1024 * 1024 / 8); //In bytes. 1024 Kbit = 128 KB - myMem.setPageSizeBytes(128); //In bytes. - myMem.enablePollForWriteComplete(); + myMem.setMemoryType(1025); // Valid types: 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1025, 2048 } void loop() diff --git a/examples/Example8_AutoDetectionTest/Example8_AutoDetectionTest.ino b/examples/Example7_AutoDetectionTest/Example7_AutoDetectionTest.ino similarity index 84% rename from examples/Example8_AutoDetectionTest/Example8_AutoDetectionTest.ino rename to examples/Example7_AutoDetectionTest/Example7_AutoDetectionTest.ino index ed652b5..53b3c84 100644 --- a/examples/Example8_AutoDetectionTest/Example8_AutoDetectionTest.ino +++ b/examples/Example7_AutoDetectionTest/Example7_AutoDetectionTest.ino @@ -20,7 +20,7 @@ 24xx128 - 131072 bit / 16384 bytes - 2 address bytes, 64 byte page size 24xx256 - 262144 bit / 32768 bytes - 2 address bytes, 64 byte page size 24xx512 - 524288 bit / 65536 bytes - 2 address bytes, 128 byte page size - 24xx1024 - 1024000 bit / 128000 byte - 2 address bytes, 128 byte page size + 24xx1025 - 1024000 bit / 128000 byte - 2 address bytes, 128 byte page size 24xxM02 - 2097152 bit / 262144 byte - 2 address bytes, 256 byte page size */ @@ -38,23 +38,6 @@ void setup() //randomSeed(analogRead(A0) * analogRead(A1)); - //The memory specs can be set before begin() to skip the auto-detection delay and write wear - //24XX02 - 2048 bit / 256 bytes - 1 address byte, 8 byte page size - //myMem.setAddressBytes(1); - //myMem.setPageSizeBytes(8); - //myMem.setMemorySizeBytes(256); - - //24XX16 - 16384 bit / 2048 bytes - 1 address byte, 16 byte page size - //myMem.setAddressBytes(1); - //myMem.setPageSizeBytes(16); - //myMem.setMemorySizeBytes(2048); - - //24XX32 - 32768 bit / 4096 bytes - 2 address byte, 32 byte page size - //myMem.setAddressBytes(2); - //myMem.setPageSizeBytes(32); - //myMem.setMemorySizeBytes(4096); - - //If specs are not available at start, they are auto-detected if (myMem.begin() == false) { Serial.println("No memory detected. Freezing."); @@ -76,7 +59,7 @@ void setup() // // while (1); - //Write a series of bytes then test to see if auto detect changes them + //Write a series of bytes then test to see if auto-detect changes them //The detection functions *should not* modify the data on the EEPROM int maxBytes = 300; //Ideally we write this many bytes @@ -143,14 +126,14 @@ void setup() myMem.write(0, myValue1); //(location, data) byte myRead1 = myMem.read(0); - Serial.print("I read: "); + Serial.print("I read (should be 200): "); Serial.println(myRead1); int myValue2 = -366; myMem.put(10, myValue2); //(location, data) int myRead2; myMem.get(10, myRead2); //location to read, thing to put data into - Serial.print("I read: "); + Serial.print("I read (should be -366): "); Serial.println(myRead2); if (myMem.getMemorySizeBytes() > 16) @@ -159,7 +142,7 @@ void setup() myMem.put(20, myValue3); //(location, data) float myRead3; myMem.get(20, myRead3); //location to read, thing to put data into - Serial.print("I read: "); + Serial.print("I read (should be -7.35): "); Serial.println(myRead3); String myString = "Hi, I am just a simple test string"; //34 characters diff --git a/examples/Example8_InterfaceTest/Example8_InterfaceTest.ino b/examples/Example8_InterfaceTest/Example8_InterfaceTest.ino new file mode 100644 index 0000000..ff8de05 --- /dev/null +++ b/examples/Example8_InterfaceTest/Example8_InterfaceTest.ino @@ -0,0 +1,553 @@ +/* + Read and write settings and calibration data to an external I2C EEPROM + By: Nathan Seidle + SparkFun Electronics + Date: December 11th, 2019 + License: This code is public domain but you buy me a beer if you use this + and we meet someday (Beerware license). + Feel like supporting our work? Buy a board from SparkFun! + https://www.sparkfun.com/products/18355 + + This example demonstrates how to read and write various variables to memory. + + The I2C EEPROM should have all its ADR pins set to GND (0). This is default + on the Qwiic board. + + Known/compatible memory types (basically all I2C EEPROMs): + 24xx00 - 128 bit / 16 bytes - 1 address byte, 1 byte page size + 24xx01 - 1024 bit / 128 bytes - 1 address byte, 8 byte page size + 24xx02 - 2048 bit / 256 bytes - 1 address byte, 8 byte page size + 24xx04 - 4096 bit / 512 bytes - 1 address byte, 16 byte page size + 24xx08 - 8192 bit / 1024 bytes - 1 address byte, 16 byte page size + 24xx16 - 16384 bit / 2048 bytes - 1 address byte, 16 byte page size + 24xx32 - 32768 bit / 4096 bytes - 2 address bytes, 32 byte page size + 24xx64 - 65536 bit / 8192 bytes - 2 address bytes, 32 byte page size + 24xx128 - 131072 bit / 16384 bytes - 2 address bytes, 64 byte page size + 24xx256 - 262144 bit / 32768 bytes - 2 address bytes, 64 byte page size + 24xx512 - 524288 bit / 65536 bytes - 2 address bytes, 128 byte page size + 24xx1024 - 1024000 bit / 128000 byte - 2 address bytes, 128 byte page size + 24xxM02 - 2097152 bit / 262144 byte - 2 address bytes, 256 byte page size + + Hardware Connections: + Plug the SparkFun Qwiic EEPROM to an Uno, Artemis, or other Qwiic equipped board + Load this sketch + Open output window at 115200bps +*/ + +#include + +#include "SparkFun_External_EEPROM.h" // Click here to get the library: http://librarymanager/All#SparkFun_External_EEPROM +ExternalEEPROM myMem; + +void setup() +{ + Serial.begin(115200); + delay(10); + Serial.println("I2C EEPROM example"); + + // Pick any unconnected analog pin + randomSeed(analogRead(A0)); + // randomSeed(analogRead(A15)); + + unsigned int randomLocation; + + Wire.begin(); + Wire.setClock(400000); + // Wire.setClock(1000000); + + // Set the memory specs + // 24xx00 - 128 bit / 16 bytes - 1 address byte, 1 byte page + // 24xx01 - 1024 bit / 128 bytes - 1 address byte, 8 byte page + // 24xx02 - 2048 bit / 256 bytes - 1 address byte, 8 byte page + // 24xx04 - 4096 bit / 512 bytes - 1 address byte, 16 byte page + // 24xx08 - 8192 bit / 1024 bytes - 1 address byte, 16 byte page + // 24xx16 - 16384 bit / 2048 bytes - 1 address byte, 16 byte page + // 24xx32 - 32768 bit / 4096 bytes - 2 address bytes, 32 byte page + // 24xx64 - 65536 bit / 8192 bytes - 2 address bytes, 32 byte page + // 24xx128 - 131072 bit / 16384 bytes - 2 address bytes, 64 byte page + // 24xx256 - 262144 bit / 32768 bytes - 2 address bytes, 64 byte page + // 24xx512 - 524288 bit / 65536 bytes - 2 address bytes, 128 byte page + // 24xx1024 - 1024000 bit / 128000 byte - 2 address byte, 128 byte page + // 24xxM02 - 2097152 bit / 262144 byte - 2 address bytes, 256 byte page + + // Before running the interface test, the memory type needs to be set, OR the memory + // size/address bytes/page size needs to be set. But not both. + + // setMemoryType() sets the memorySizeBytes, addressBytes, and pageSizeBytes variables. + // myMem.setMemoryType(512); // Valid types: 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048 + + // If setMemorySizeBytes/setAddressBytes/setPageSizeBytes() are called, they will overwrite + // any previous settings set by setMemoryType(). + myMem.setMemorySizeBytes(65536); + myMem.setAddressBytes(2); // Set address bytes and page size after MemorySizeBytes() + myMem.setPageSizeBytes(128); + + if (myMem.begin() == false) + { + Serial.println("No memory detected. Freezing."); + while (1) + ; + } + Serial.println("Memory detected!"); + + uint32_t eepromSizeBytes = myMem.getMemorySizeBytes(); + Serial.print("EEPROM type: 24xx"); + if (eepromSizeBytes == 16) + Serial.print("00"); + else + { + if ((eepromSizeBytes * 8 / 1024) < 10) + Serial.print("0"); + Serial.print(eepromSizeBytes * 8 / 1024); + } + Serial.print(" - bytes: "); + Serial.print(eepromSizeBytes); + Serial.println(); + + Serial.print("Number of address bytes: "); + Serial.println(myMem.getAddressBytes()); + + Serial.print("Page size in bytes: "); + Serial.println(myMem.getPageSizeBytes()); + + bool allTestsPassed = true; + + // Erase test + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + Serial.print("Time to erase all EEPROM: "); + long startTime = millis(); + myMem.erase(); + long endTime = millis(); + Serial.print(endTime - startTime); + Serial.println("ms"); + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + + // Byte sequential test + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + Serial.println(); + Serial.println("8 bit tests"); + byte myValue1 = 200; + byte myValue2 = 23; + randomLocation = random(0, myMem.length() - (sizeof(byte) * 2)); + + startTime = micros(); + myMem.write(randomLocation, myValue1); //(location, data) + while (myMem.isConnected() == false) + ; // Wait for write to complete + endTime = micros(); + Serial.print("Time to record byte: "); + Serial.print(endTime - startTime); + Serial.println(" us"); + + myMem.put(randomLocation + sizeof(byte), myValue2); + while (myMem.isConnected() == false) + ; // Wait for write to complete + + startTime = micros(); + myMem.write(randomLocation, myValue1); //(location, data) + while (myMem.isConnected() == false) + ; // Wait for write to complete + endTime = micros(); + Serial.print("Time to write identical byte to same location (should be ~0ms): "); + Serial.print(endTime - startTime); + Serial.println(" us"); + + startTime = micros(); + byte response1 = myMem.read(randomLocation); + endTime = micros(); + Serial.print("Time to read byte: "); + Serial.print(endTime - startTime); + Serial.println(" us"); + + byte response2 = myMem.read(randomLocation + sizeof(byte)); + Serial.print("Location "); + Serial.print(randomLocation); + Serial.print(" should be "); + Serial.print(myValue1); + Serial.print(": "); + Serial.print(response1); + if (myValue1 == response1 ? Serial.print(" - Success") : Serial.print(" - Fail")) + ; + Serial.println(); + + Serial.print("Location "); + Serial.print(randomLocation + sizeof(byte)); + Serial.print(" should be "); + Serial.print(myValue2); + Serial.print(": "); + Serial.print(response2); + if (myValue2 == response2 ? Serial.print(" - Success") : Serial.print(" - Fail")) + ; + Serial.println(); + + if (myValue1 != response1) + allTestsPassed = false; + if (myValue2 != response2) + allTestsPassed = false; + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + + Serial.println(""); + Serial.println("16 bit tests"); + + // int16_t and uint16_t tests + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + uint16_t myValue3 = 3411; + int16_t myValue4 = -366; + randomLocation = random(0, myMem.length() - (sizeof(int16_t) * 2)); + + startTime = micros(); + myMem.put(randomLocation, myValue3); + endTime = micros(); + Serial.print("Time to record int16: "); + Serial.print(endTime - startTime); + Serial.println(" us"); + + myMem.put(randomLocation + sizeof(int16_t), myValue4); + + uint16_t response3; + int16_t response4; + + startTime = micros(); + myMem.get(randomLocation, response3); + endTime = micros(); + Serial.print("Time to read int16: "); + Serial.print(endTime - startTime); + Serial.println(" us"); + + myMem.get(randomLocation + sizeof(int16_t), response4); + Serial.print("Location "); + Serial.print(randomLocation); + Serial.print(" should be "); + Serial.print(myValue3); + Serial.print(": "); + Serial.print(response3); + if (myValue3 == response3 ? Serial.print(" - Success") : Serial.print(" - Fail")) + ; + Serial.println(); + + Serial.print("Location "); + Serial.print(randomLocation + sizeof(int16_t)); + Serial.print(" should be "); + Serial.print(myValue4); + Serial.print(": "); + Serial.print(response4); + if (myValue4 == response4 ? Serial.print(" - Success") : Serial.print(" - Fail")) + ; + Serial.println(); + + if (myValue3 != response3) + allTestsPassed = false; + if (myValue4 != response4) + allTestsPassed = false; + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + + Serial.println(""); + Serial.println("int tests"); + + // int and unsigned int tests + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + Serial.print("Size of int: "); + Serial.println(sizeof(int)); // Uno reports this as 2 + int myValue5 = -2450; + unsigned int myValue6 = 4001; + randomLocation = random(0, myMem.length() - (sizeof(int) * 2)); + + startTime = micros(); + myMem.put(randomLocation, myValue5); + endTime = micros(); + Serial.print("Time to record int: "); + Serial.print(endTime - startTime); + Serial.println(" us"); + myMem.put(randomLocation + sizeof(int), myValue6); + + int response5; + unsigned int response6; + + startTime = micros(); + myMem.get(randomLocation, response5); + endTime = micros(); + Serial.print("Time to read int: "); + Serial.print(endTime - startTime); + Serial.println(" us"); + + myMem.get(randomLocation + sizeof(int), response6); + Serial.print("Location "); + Serial.print(randomLocation); + Serial.print(" should be "); + Serial.print(myValue5); + Serial.print(": "); + Serial.print(response5); + if (myValue5 == response5 ? Serial.print(" - Success") : Serial.print(" - Fail")) + ; + Serial.println(); + + Serial.print("Location "); + Serial.print(randomLocation + sizeof(int)); + Serial.print(" should be "); + Serial.print(myValue6); + Serial.print(": "); + Serial.print(response6); + if (myValue6 == response6 ? Serial.print(" - Success") : Serial.print(" - Fail")) + ; + Serial.println(); + + if (myValue5 != response5) + allTestsPassed = false; + if (myValue6 != response6) + allTestsPassed = false; + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + + Serial.println(""); + Serial.println("32 bit tests"); + + // int32_t and uint32_t sequential test + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + int32_t myValue7 = -341002; + uint32_t myValue8 = 241544; + randomLocation = random(0, myMem.length() - (sizeof(int32_t) * 2)); + + myMem.put(randomLocation, myValue7); + myMem.put(randomLocation + sizeof(int32_t), myValue8); + + int32_t response7; + uint32_t response8; + + startTime = micros(); + myMem.get(randomLocation, response7); + endTime = micros(); + Serial.print("Time to read int32: "); + Serial.print(endTime - startTime); + Serial.println(" us"); + + myMem.get(randomLocation + sizeof(int32_t), response8); + Serial.print("Location "); + Serial.print(randomLocation); + Serial.print(" should be "); + Serial.print(myValue7); + Serial.print(": "); + Serial.print(response7); + if (myValue7 == response7 ? Serial.print(" - Success") : Serial.print(" - Fail")) + ; + Serial.println(); + + Serial.print("Location "); + Serial.print(randomLocation + sizeof(int32_t)); + Serial.print(" should be "); + Serial.print(myValue8); + Serial.print(": "); + Serial.print(response8); + if (myValue8 == response8 ? Serial.print(" - Success") : Serial.print(" - Fail")) + ; + Serial.println(); + + if (myValue7 != response7) + allTestsPassed = false; + if (myValue8 != response8) + allTestsPassed = false; + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + + // float (32) sequential test + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + Serial.print("Size of float: "); + Serial.println(sizeof(float)); + float myValue9 = -7.35; + float myValue10 = 5.22; + randomLocation = random(0, myMem.length() - (sizeof(float) * 2)); + + myMem.put(randomLocation, myValue9); + myMem.put(randomLocation + sizeof(float), myValue10); + + float response9; + float response10; + + startTime = micros(); + myMem.get(randomLocation, response9); + endTime = micros(); + Serial.print("Time to read float: "); + Serial.print(endTime - startTime); + Serial.println(" us"); + + myMem.get(randomLocation + sizeof(float), response10); + Serial.print("Location "); + Serial.print(randomLocation); + Serial.print(" should be "); + Serial.print(myValue9); + Serial.print(": "); + Serial.print(response9); + if (myValue9 == response9 ? Serial.print(" - Success") : Serial.print(" - Fail")) + ; + Serial.println(); + + Serial.print("Location "); + Serial.print(randomLocation + sizeof(float)); + Serial.print(" should be "); + Serial.print(myValue10); + Serial.print(": "); + Serial.print(response10); + if (myValue10 == response10 ? Serial.print(" - Success") : Serial.print(" - Fail")) + ; + Serial.println(); + + if (myValue9 != response9) + allTestsPassed = false; + if (myValue10 != response10) + allTestsPassed = false; + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + + Serial.println(""); + Serial.println("64 bit tests"); + + // double (64) sequential test + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + Serial.print("Size of double: "); + Serial.println(sizeof(double)); + double myValue11 = -290.3485723409857; + double myValue12 = 384.957; // 34987; + double myValue13 = 917.14159; + double myValue14 = 254.8877; + randomLocation = random(0, myMem.length() - (sizeof(double) * 2)); + + startTime = micros(); + myMem.put(randomLocation, myValue11); + endTime = micros(); + Serial.print("Time to record 64-bits: "); + Serial.print(endTime - startTime); + Serial.println(" us"); + + myMem.put(randomLocation + sizeof(double), myValue12); + myMem.put(myMem.length() - sizeof(double), myValue13); // Test end of EEPROM space + + double response11; + double response12; + double response13; + + startTime = micros(); + myMem.get(randomLocation, response11); + endTime = micros(); + Serial.print("Time to read 64-bits: "); + Serial.print(endTime - startTime); + Serial.println(" us"); + + myMem.get(randomLocation + sizeof(double), response12); + myMem.get(myMem.length() - sizeof(double), response13); + Serial.print("Location "); + Serial.print(randomLocation); + Serial.print(" should be "); + Serial.print(myValue11); + Serial.print(": "); + Serial.print(response11); + if (myValue11 == response11 ? Serial.print(" - Success") : Serial.print(" - Fail")) + ; + Serial.println(); + + Serial.print("Location "); + Serial.print(randomLocation + sizeof(double)); + Serial.print(" should be "); + Serial.print(myValue12); + Serial.print(": "); + Serial.print(response12); + if (myValue12 == response12 ? Serial.print(" - Success") : Serial.print(" - Fail")) + ; + Serial.println(); + + Serial.print("Edge of EEPROM "); + Serial.print(myMem.length() - sizeof(double)); + Serial.print(" should be "); + Serial.print(myValue13); + Serial.print(": "); + Serial.print(response13); + if (myValue13 == response13 ? Serial.print(" - Success") : Serial.print(" - Fail")) + ; + Serial.println(); + + double response14; + myMem.put(myMem.length() - sizeof(double), myValue14); // Test the re-write of a spot + myMem.get(myMem.length() - sizeof(double), response14); + Serial.print("Rewrite of "); + Serial.print(myMem.length() - sizeof(double)); + Serial.print(" should be "); + Serial.print(myValue14); + Serial.print(": "); + Serial.print(response14); + if (myValue14 == response14 ? Serial.print(" - Success") : Serial.print(" - Fail")) + ; + Serial.println(); + + if (myValue11 != response11) + allTestsPassed = false; + if (myValue12 != response12) + allTestsPassed = false; + if (myValue13 != response13) + allTestsPassed = false; + if (myValue14 != response14) + allTestsPassed = false; + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + + Serial.println(""); + Serial.println("Buffer Write Test"); + + // Buffer write test + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + // char myChars[242] = "Lorem ipsum dolor sit amet, has in verterem accusamus. Nulla viderer inciderint eum at. Quo + // elit nullam malorum te, agam fuisset detracto an sea, eam ut liber aperiri. Id qui velit facilisi. Mel probatus + // definitionem id, eu amet vidisse eum."; + char myChars[88] = "Lorem ipsum dolor sit amet, has in verterem accusamus. Nulla viderer inciderint eum at."; + randomLocation = random(0, myMem.length() - sizeof(myChars)); + + Serial.print("Calculated time to record array of "); + Serial.print(sizeof(myChars)); + Serial.print(" characters: ~"); + Serial.print((uint32_t)sizeof(myChars) / myMem.getPageSizeBytes() * myMem.getWriteTimeMs()); + Serial.println("ms"); + + startTime = micros(); + myMem.put(randomLocation, myChars); + endTime = micros(); + Serial.print("Time to record array: "); + Serial.print(endTime - startTime); + Serial.println(" us"); + + char readMy[sizeof(myChars)]; + + startTime = micros(); + myMem.get(randomLocation, readMy); + endTime = micros(); + Serial.print("Time to read array: "); + Serial.print(endTime - startTime); + Serial.println(" us"); + + // Serial.print("Location "); + // Serial.print(randomLocation); + // Serial.print(" string should read:"); + // Serial.println(myChars); + // Serial.println(readMy); + if (strcmp(myChars, readMy) != 0) + { + Serial.println("String compare failed"); + allTestsPassed = false; + } + + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + + Serial.println(); + Serial.print("Memory Contents:"); + for (uint16_t x = 0; x < 32 * 4; x++) + { + if (x % 16 == 0) + Serial.println(); + Serial.print(" 0x"); + if (myMem.read(x) < 0x10) + Serial.print("0"); + Serial.print(myMem.read(x), HEX); + } + Serial.println(); + + if (allTestsPassed == true) + Serial.println("All tests PASSED!"); + else + Serial.println("Something went wrong. See output."); +} + +void loop() +{ +} \ No newline at end of file diff --git a/examples/Example9_SaveChangedSettings/Example9_SaveChangedSettings.ino b/examples/Example9_SaveChangedSettings/Example9_SaveChangedSettings.ino new file mode 100644 index 0000000..d1a7dca --- /dev/null +++ b/examples/Example9_SaveChangedSettings/Example9_SaveChangedSettings.ino @@ -0,0 +1,289 @@ +/* + Read and write data to an external I2C EEPROM + By: Nathan Seidle, Merlin Z + SparkFun Electronics + Date: July 11, 2024 + License: This code is public domain but you buy me a coffee if you use this + and we meet someday (Beerware license). + Feel like supporting our work? Buy a board from SparkFun! + https://www.sparkfun.com/products/18355 + + This example demonstrates how to record various user settings easily to + EEPROM, only writing settings that changed in order to preserve the life of + the memory. Use the ExternalEEPROM::putChanged() method instead of + External_EEPROM::put() to do this. + + The I2C EEPROM should have all its ADR pins set to GND (0). This is default + on the Qwiic board. + + Hardware Connections: + Plug the SparkFun Qwiic EEPROM to an Uno, Artemis, or other Qwiic equipped + board. + Load this sketch. + Open serial monitor window with baud rate at 115200 and line ending set to + Line Feed. +*/ + +// Include the necessary libraries +#include + +// Click here to get the library: +// http://librarymanager/All#SparkFun_External_EEPROM +// or download the zip here: +// https://github.com/sparkfun/SparkFun_External_EEPROM_Arduino_Library/archive/master.zip +#include "SparkFun_External_EEPROM.h" + +// Declare the EEPROM object +ExternalEEPROM myMem; + +// This is the position in EEPROM to store the settings struct +#define LOCATION_SETTINGS 0 + +// This is the data that we use to validate the EEPROM data. +// The __TIME__ macro is the time the sketch was compiled, in HH:MM:SS format. +// This means that if the sketch is recompiled, the EEPROM data will be +// considered invalid, +#define VALID_DATA __TIME__ + +// This is the struct that contains all the settings. +// Add as many vars as you want. +typedef struct { + // This first buffer is used to determine if the EEPROM has + // been written to with valid data. If the bytes match the VALID_DATA + // constant, then we can assume the data is valid. + char memoryIsValid[sizeof(VALID_DATA)]; + // A baud rate setting (doesn't actually do anything in this example) + unsigned long baudRate; + // A setting to enable or disable the built-in LED + bool enableLED; +} Settings; + +// This is the settings object. +Settings settings; + +void setup() { + // Set up serial communication + Serial.begin(115200); + // delay(250); // Often needed for ESP based platforms + + while (!Serial.available()) { + Serial.println(F("Press any key to begin.")); + delay(1000); + } + Serial.println(F("EEPROM load/save example")); + + // Initialize I2C + Wire.begin(); + + // Configure the EEPROM + // Default to the Qwiic 24xx512 EEPROM: + // https://www.sparkfun.com/products/18355 + // Valid types: 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1025, 2048 + // For example, to use a 24C02 EEPROM, set the memory type to 2 + // Make sure to set this correctly or this example won't work! + myMem.setMemoryType(2); + + // Initialize the EEPROM + if (myMem.begin() == false) { + Serial.println(F("No memory detected. Freezing.")); + while (true); + } + Serial.println(F("Memory detected!")); + + // Print out the size of the user settings struct + Serial.print("Size of user settings in bytes: "); + Serial.println(sizeof(settings)); + + Serial.println("Settings are not initialized or loaded from EEPROM."); + + // Present user menu + mainMenu(); +} + +void loop() { + if (Serial.available()) mainMenu(); // Present user menu +} + +void mainMenu() { + int number; + while (1) { + Serial.println(); + Serial.println("Main menu:"); + Serial.println(); + Serial.println("P: Print Settings"); + Serial.println("L: Load Settings"); + Serial.println("S: Save Settings"); + Serial.println("R: Reset Settings to Default"); + Serial.println("B: Set Baud Rate"); + Serial.println("T: Toggle LED Setting"); + Serial.println(); + Serial.print("Enter choice: "); + + byte selection = readByte(); + + switch (selection) { + case 'p': + case 'P': + printSettings(); + break; + case 'l': + case 'L': + loadSettings(); + break; + case 's': + case 'S': + saveSettings(); + break; + case 'r': + case 'R': + resetSettings(); + break; + case 'b': + case 'B': + Serial.print("Enter baud rate (1200 to 115200): "); + number = readNumber(); + if (number < 1200 || number > 115200) { + Serial.println("Error: baud rate out of range"); + } else { + settings.baudRate = number; + } + break; + case 't': + case 'T': + settings.enableLED = !settings.enableLED; + syncLED(); + Serial.print("LED is now "); + Serial.println(settings.enableLED ? "on" : "off"); + break; + default: + Serial.print("Unknown choice: "); + Serial.write(selection); + Serial.println(); + } + } +} + +// Blocking wait for user input +void waitForInput() { + delay(10); // Wait for any incoming chars to hit buffer + while (Serial.available() > 0) Serial.read(); // Clear buffer + while (Serial.available() == 0); +} + +// Get single byte from user. +// Waits for and returns the character that the user provides +byte readByte() { + waitForInput(); + return (Serial.read()); +} + +// Get a string/value from user, remove all non-numeric values +int readNumber() { + waitForInput(); + + char numberString[20 + 1]; // Room for 20 digits plus terminating \0 + + int index = 0; + while (index < 20) { + // Wait for user input + while (Serial.available() == 0); + + // Read the incoming byte + byte incoming = Serial.read(); + + // If the user hits enter, we're done + if (incoming == '\n' || incoming == '\r') { + Serial.println(); + break; + } + + // Check for a digit + if (isDigit(incoming) == true) { + // Echo the digit + Serial.write(incoming); + // Add the digit to the string + numberString[index] = (char)incoming; + index++; + } + } + + // Null terminate the string + numberString[index] = '\0'; + + // Convert the string to an integer and return it + String tempValue = numberString; + return (tempValue.toInt()); +} + +// This function is called to sync the LED state with the settings +// (On my board at least), the LED is active low, so we invert the setting +void syncLED() { digitalWrite(PIN_LED, !settings.enableLED); } + +// Reset the settings struct to default values (without writing to EEPROM) +void resetSettings() { + // Set the first 8 bytes of the settings struct to the VALID_DATA constant + memcpy(settings.memoryIsValid, VALID_DATA, sizeof(settings.memoryIsValid)); + // Set the baud rate to 9600 + settings.baudRate = 9600; + // Set the LED to off + settings.enableLED = false; + syncLED(); + + Serial.println("Settings reset to default."); +} + +// Load the current settings from EEPROM into the settings struct +void loadSettings() { + // Call the get() method with the location and the struct to load into + myMem.get(LOCATION_SETTINGS, settings); + + // Sync the LED with the settings + syncLED(); + + Serial.println("Settings loaded from EEPROM."); + + if (memcmp(settings.memoryIsValid, VALID_DATA, + sizeof(settings.memoryIsValid)) != 0) { + Serial.println( + "Memory is not valid. You should reset the settings and save them."); + // In a real application, you would do this here: + // resetSettings(); + // saveSettings(); + } else { + Serial.println("Memory is valid!"); + } +} + +// Record the current settings into EEPROM +void saveSettings() { + // The putChanged() method writes the data to the EEPROM + // (the same as the put() method except it only writes data that changed). + myMem.put(LOCATION_SETTINGS, settings); + + Serial.println("Settings saved to EEPROM."); +} + +// Print the current settings to the serial monitor +void printSettings() { + Serial.println("Current settings:"); + Serial.println(); + + Serial.print("Memory valid: "); + for (int i = 0; i < sizeof(settings.memoryIsValid); i++) { + Serial.print(settings.memoryIsValid[i], 16); + Serial.print(' '); + } + Serial.println(); + Serial.print(" VALID_DATA: "); + for (int i = 0; i < sizeof(settings.memoryIsValid); i++) { + Serial.print(VALID_DATA[i], 16); + Serial.print(' '); + } + Serial.println(); + + Serial.print("Baud rate: "); + Serial.println(settings.baudRate); + + Serial.print("LED: "); + Serial.println(settings.enableLED ? "on" : "off"); +} diff --git a/keywords.txt b/keywords.txt index 8a9a5e8..591ba02 100644 --- a/keywords.txt +++ b/keywords.txt @@ -12,36 +12,20 @@ ExternalEEPROM KEYWORD1 # Methods and Functions (KEYWORD2) ####################################### -read KEYWORD2 -write KEYWORD2 begin KEYWORD2 isConnected KEYWORD2 isBusy KEYWORD2 +read KEYWORD2 +write KEYWORD2 erase KEYWORD2 - -detectMemorySizeBytes KEYWORD2 -setMemorySizeBytes KEYWORD2 -getMemorySizeBytes KEYWORD2 setMemorySize KEYWORD2 getMemorySize KEYWORD2 +setMemoryType KEYWORD2 length KEYWORD2 - -detectPageSizeBytes KEYWORD2 -setPageSizeBytes KEYWORD2 -getPageSizeBytes KEYWORD2 setPageSize KEYWORD2 getPageSize KEYWORD2 - -detectAddressBytes KEYWORD2 -setAddressBytes KEYWORD2 -getAddressBytes KEYWORD2 - -detectWriteTimeMs KEYWORD2 -setWriteTimeMs KEYWORD2 -getWriteTimeMs KEYWORD2 setPageWriteTime KEYWORD2 getPageWriteTime KEYWORD2 - enablePollForWriteComplete KEYWORD2 disablePollForWriteComplete KEYWORD2 get KEYWORD2 @@ -50,7 +34,6 @@ setI2CBufferSize KEYWORD2 getI2CBufferSize KEYWORD2 putString KEYWORD2 getString KEYWORD2 -detectMemorySizeBytes KEYWORD2 ####################################### # Constants (LITERAL1) diff --git a/library.properties b/library.properties index 4f23fbd..8cc576c 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ name=SparkFun External EEPROM Arduino Library -version=3.0.0 +version=3.2.10 author=SparkFun Electronics maintainer=SparkFun Electronics sentence=Library for I2C Communication with external EEPROMs -paragraph=A library for the advanced control of any I2C based EEPROM. This library writes extremely fast and automatically handles the writing of pages to make the entire EEPROM act as one large writable block. Automatically reads and writes ints, floats, arrays, and structs. Automatically detected EEPROM specs including memory size, page size, address bytes, and write times. Works with all EEPROMs including very large >512kbit EEPROMs and any Wire port (Wire1, etc). Use with Qwiic EEPROM to make it easy to read and write cal data and other user settings. Configurable I2C buffer size increases throughput up to 30kB/s. Includes an example that reads binary file from SD and auto writes/verifies to EEPROM. Tested with 24LC00, 24LC01B, 24AA02, 24LC04B, 24LC16BH, 24LC32A, 24LC256, CAT24C512, 24LC1025, and 24LC1026. +paragraph=A library for the advanced control of any I2C based EEPROM. This library writes extremely fast and automatically handles the writing of pages to make the entire EEPROM act as one large writable block. Automatically reads and writes ints, floats, arrays, and structs. Works with all EEPROMs including very large >512kbit EEPROMs and any Wire port (Wire1, etc). Use with Qwiic EEPROM to make it easy to read and write cal data and other user settings. Configurable I2C buffer size increases throughput up to 30kB/s. Includes examples demonstrating wear-level writing, SD file to EEPROM write, and auto writes/verifies to EEPROM. Tested with 24LC00, 24LC01B, 24AA02, 24LC04B, 24LC16BH, 24LC32A, 24LC256, CAT24C512, 24LC1025, and 24LC1026. category=Data Storage url=https://github.com/sparkfun/SparkFun_External_EEPROM_Arduino_Library architectures=* diff --git a/src/SparkFun_External_EEPROM.cpp b/src/SparkFun_External_EEPROM.cpp index 6a6482c..9e77938 100644 --- a/src/SparkFun_External_EEPROM.cpp +++ b/src/SparkFun_External_EEPROM.cpp @@ -4,7 +4,7 @@ EEPROM library so you can use the same get() and put() functions. https://github.com/sparkfun/SparkFun_External_EEPROM_Arduino_Library - Best used with the Qwiic EEPROM: https://www.sparkfun.com/products/14764 + Best used with the Qwiic EEPROM: https://www.sparkfun.com/products/18355 Various external EEPROMs have various interface specs (overall size, page size, write times, etc). This library works with @@ -26,8 +26,14 @@ #include "Arduino.h" #include "Wire.h" -bool ExternalEEPROM::begin(uint8_t deviceAddress, TwoWire &wirePort) +bool ExternalEEPROM::begin(uint8_t deviceAddress, TwoWire &wirePort, uint8_t WP) { + if(WP != 255) + { + pinMode(WP, OUTPUT); + digitalWrite(WP, HIGH); + settings.wpPin = WP; + } settings.i2cPort = &wirePort; // Grab which port the user wants us to use settings.deviceAddress = deviceAddress; @@ -124,12 +130,122 @@ uint32_t ExternalEEPROM::getMemorySize() void ExternalEEPROM::setMemorySizeBytes(uint32_t memSize) { settings.memorySize_bytes = memSize; + + //Try to identify this memory size settings + switch (memSize) + { + default: + // Unknown memory size + break; + case (16): + setAddressBytes(1); + setPageSizeBytes(1); + break; + case (128): + setAddressBytes(1); + setPageSizeBytes(8); + break; + case (256): + setAddressBytes(1); + setPageSizeBytes(8); + break; + case (512): + setAddressBytes(1); + setPageSizeBytes(16); + break; + case (1024): + setAddressBytes(1); + setPageSizeBytes(16); + break; + case (2048): + setAddressBytes(1); + setPageSizeBytes(16); + break; + case (4096): + setAddressBytes(2); + setPageSizeBytes(32); + break; + case (8192): + setAddressBytes(2); + setPageSizeBytes(32); + break; + case (16384): + setAddressBytes(2); + setPageSizeBytes(64); + break; + case (32768): + setAddressBytes(2); + setPageSizeBytes(64); + break; + case (65536): + setAddressBytes(2); + setPageSizeBytes(128); + break; + case (128000): + setAddressBytes(2); + setPageSizeBytes(128); + break; + case (262144): + setAddressBytes(2); + setPageSizeBytes(256); + break; + } } uint32_t ExternalEEPROM::getMemorySizeBytes() { return settings.memorySize_bytes; } +void ExternalEEPROM::setMemoryType(uint16_t typeNumber) +{ + //Set settings based on known memory types + switch (typeNumber) + { + default: + // Unknown type number + break; + case (0): + setMemorySizeBytes(16); + break; + case (1): + setMemorySizeBytes(128 * (uint32_t)typeNumber); //128 + break; + case (2): + setMemorySizeBytes(128 * (uint32_t)typeNumber); //256 + break; + case (4): + setMemorySizeBytes(128 * (uint32_t)typeNumber); //512 + break; + case (8): + setMemorySizeBytes(128 * (uint32_t)typeNumber); //1024 + break; + case (16): + setMemorySizeBytes(128 * (uint32_t)typeNumber); //2048 + break; + case (32): + setMemorySizeBytes(128 * (uint32_t)typeNumber); //4096 + break; + case (64): + setMemorySizeBytes(128 * (uint32_t)typeNumber); //8192 + break; + case (128): + setMemorySizeBytes(128 * (uint32_t)typeNumber); //16384 + break; + case (256): + setMemorySizeBytes(128 * (uint32_t)typeNumber); //32768 + break; + case (512): + setMemorySizeBytes(128 * (uint32_t)typeNumber); //65536 + break; + case (1025): + setMemorySizeBytes(128000); //128000 + break; + case (2048): + setMemorySizeBytes(262144); //262144 + break; + } +} + // Old get/setPageSize. Use get/setPageSizeBytes void ExternalEEPROM::setPageSize(uint16_t pageSize) { @@ -475,12 +591,10 @@ uint16_t ExternalEEPROM::detectPageSizeBytes() // For EEPROMs of 4k, 8k, and 16k bit, there are three bits called // 'block select bits' inside the address byte that are used // For 32k, 64k, 128k, 256k, and 512k bit we need two address bytes -// At 1Mbit (128,000 byte) and above there are two address bytes and a block select bit +// At 1Mbit (128,000 byte) and above there are two address bytes and a block select bit // is used but at the upper end of the address bits (so instead of A2/A1/A0 it's B0/A1/A0). uint32_t ExternalEEPROM::detectMemorySizeBytes() { - uint8_t i2cAddress = settings.deviceAddress; - // We do a read-write-read-write to test. uint32_t testLocation = (128 / 8) - 1; // Start at the last spot of the smallest EEPROM uint32_t lastGoodLocation = 0; @@ -512,8 +626,6 @@ uint32_t ExternalEEPROM::detectMemorySizeBytes() // 4 Check value at next threshold. If it was changed then we know the address we wrote was wrapped. // 5 Return memory spot to its original value - int loopCount = 1; - while (1) { // We must set our memory size to the next size up so that write sets the correct bits @@ -765,6 +877,9 @@ int ExternalEEPROM::write(uint32_t eepromLocation, const uint8_t *dataToWrite, u while (isBusy(settings.deviceAddress) == true) // Poll device's original address, not the modified one delayMicroseconds(100); // This shortens the amount of time waiting between writes but hammers the I2C bus + // Check if we are using Write Protection then disable WP for write access + if(settings.wpPin != 255 ) digitalWrite(settings.wpPin, LOW); + settings.i2cPort->beginTransmission(i2cAddress); if (settings.addressSize_bytes > 1) // Device larger than 16,384 bits have two byte addresses settings.i2cPort->write((uint8_t)((eepromLocation + recorded) >> 8)); // MSB @@ -782,6 +897,9 @@ int ExternalEEPROM::write(uint32_t eepromLocation, const uint8_t *dataToWrite, u if (settings.pollForWriteComplete == false) delay(settings.writeTime_ms); // Delay the amount of time to record a page + + // Enable Write Protection if we are using WP + if(settings.wpPin != 255) digitalWrite(settings.wpPin, HIGH); } return (result); diff --git a/src/SparkFun_External_EEPROM.h b/src/SparkFun_External_EEPROM.h index 1fd7ef3..60de7d8 100644 --- a/src/SparkFun_External_EEPROM.h +++ b/src/SparkFun_External_EEPROM.h @@ -4,7 +4,7 @@ EEPROM library so you can use the same get() and put() functions. https://github.com/sparkfun/SparkFun_External_EEPROM_Arduino_Library - Best used with the Qwiic EEPROM: https://www.sparkfun.com/products/14764 + Best used with the Qwiic EEPROM: https://www.sparkfun.com/products/18355 Various external EEPROMs have various interface specs (overall size, page size, write times, etc). This library works with @@ -40,7 +40,7 @@ #define I2C_BUFFER_LENGTH_RX BUFFER_LENGTH // I2C_BUFFER_LENGTH is defined in Wire.H #define I2C_BUFFER_LENGTH_TX BUFFER_LENGTH -#elif defined(__SAMD21G18A__) +#elif defined(__SAMD21G18A__) || defined(__SAMD21E18A__) #define I2C_BUFFER_LENGTH_RX SERIAL_BUFFER_SIZE // SAMD21 uses RingBuffer.h #define I2C_BUFFER_LENGTH_TX SERIAL_BUFFER_SIZE @@ -111,6 +111,7 @@ struct struct_memorySettings uint8_t writeTime_ms; bool pollForWriteComplete; uint8_t addressSize_bytes; + uint8_t wpPin; }; class ExternalEEPROM @@ -121,7 +122,8 @@ class ExternalEEPROM int write(uint32_t eepromLocation, uint8_t dataToWrite); int write(uint32_t eepromLocation, const uint8_t *dataToWrite, uint16_t blockSize); - bool begin(uint8_t deviceAddress = 0b1010000, TwoWire &wirePort = Wire); // By default use the Wire port + bool begin(uint8_t deviceAddress = 0b1010000, TwoWire &wirePort = Wire, uint8_t WP = 255); // By default use the Wire port + bool isConnected(uint8_t i2cAddress = 255); bool isBusy(uint8_t i2cAddress = 255); void erase(uint8_t toWrite = 0x00); // Erase the entire memory. Optional: write a given byte to each spot. @@ -135,6 +137,8 @@ class ExternalEEPROM uint32_t getMemorySize(); // Depricated uint32_t length(); // Return size of EEPROM in bytes + void setMemoryType(uint16_t typeNumber); // Valid types: 00, 01, 02, 04, 08, 16, 32, 64, 128, 256, 512, 1025, 2048 + uint8_t detectAddressBytes(); // Determine the number of address bytes, 1 or 2 void setAddressBytes(uint8_t addressBytes); uint8_t getAddressBytes(); @@ -170,6 +174,19 @@ class ExternalEEPROM return t; } + template const T &putChanged(uint32_t idx, const T &t) // Address, data + { + const uint8_t *newData = (const uint8_t *)&t; + uint8_t oldData[sizeof(T)]; + read(idx, oldData, sizeof(T)); // Address, data, sizeOfData + for (uint16_t i = 0; i < sizeof(T); i++) { + if (oldData[i] != newData[i]) { + write(idx + i, newData[i]); + } + } + return t; + } + uint32_t putString(uint32_t eepromLocation, String &strToWrite); void getString(uint32_t eepromLocation, String &strToRead); @@ -179,11 +196,12 @@ class ExternalEEPROM .i2cPort = &Wire, .deviceAddress = 0b1010000, // 0x50; format is 0b1010 + (A2 A1 A0) or 0b1010 + (B0 A1 A0) for larger (>512kbit) EEPROMs - .memorySize_bytes = 0, // Detected at begin() - .pageSize_bytes = 0, // Detected at begin() + .memorySize_bytes = 4096, // Default to 4096, to support 24xx32 / 4096 byte EEPROMs and larger + .pageSize_bytes = 32, // Default to 32 bytes, to support 24xx32 / 4096 byte EEPROMs and larger .writeTime_ms = 5, //All EEPROMs seem to have a max write time of 5ms .pollForWriteComplete = true, - .addressSize_bytes = 0, // Detected at begin() + .addressSize_bytes = 2, // Default to two address bytes, to support 24xx32 / 4096 byte EEPROMs and larger + .wpPin = 255, // By default, the write protection pin is not set }; }; pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy