#pragma once // // FILE: I2C_eeprom.h // AUTHOR: Rob Tillaart // VERSION: 1.9.4 // PURPOSE: Arduino Library for external I2C EEPROM 24LC256 et al. // URL: https://github.com/RobTillaart/I2C_EEPROM #include "Arduino.h" #include "Wire.h" #define I2C_EEPROM_VERSION (F("1.9.4")) #define I2C_DEVICESIZE_24LC512 65536 #define I2C_DEVICESIZE_24LC256 32768 #define I2C_DEVICESIZE_24LC128 16384 #define I2C_DEVICESIZE_24LC64 8192 #define I2C_DEVICESIZE_24LC32 4096 #define I2C_DEVICESIZE_24LC16 2048 #define I2C_DEVICESIZE_24LC08 1024 #define I2C_DEVICESIZE_24LC04 512 #define I2C_DEVICESIZE_24LC02 256 #define I2C_DEVICESIZE_24LC01 128 // AT24C32 has a WriteCycle Time of max 20 ms // so one need to set I2C_WRITEDELAY to 20000. // can also be done on command line. // (see private _waitEEReady() function) #ifndef I2C_WRITEDELAY #define I2C_WRITEDELAY 5000 #endif // set the flag EN_AUTO_WRITE_PROTECT to 1 to enable the Write Control at compile time // used if the write_protect pin is explicitly set in the begin() function. // the flag can be set as command line option. #ifndef EN_AUTO_WRITE_PROTECT #define EN_AUTO_WRITE_PROTECT 0 #endif #ifndef UNIT_TEST_FRIEND #define UNIT_TEST_FRIEND #endif //#define ENABLE_DEBUG #ifdef ENABLE_DEBUG #define SPRN Serial.print #define SPRNL Serial.println #define SPRNH Serial.print #define SPRNLH Serial.println #else #define SPRN(MSG) #define SPRNH(MSG,MSG2) #define SPRNL(MSG) #define SPRNLH(MSG,MSG2) #endif class I2C_eeprom { public: /** * Initializes the EEPROM with a default deviceSize of I2C_DEVICESIZE_24LC256 (32K EEPROM) */ I2C_eeprom(const uint8_t deviceAddress, TwoWire *wire = &Wire); /** * Initializes the EEPROM for the given device address. * * It will try to guess page size and address word size based on the size of the device. * * @param deviceAddress Byte address of the device. * @param deviceSize Max size in bytes of the device (divide your device size in Kbits by 8 to get Kbytes) * @param wire Select alternative Wire interface */ I2C_eeprom(const uint8_t deviceAddress, const uint32_t deviceSize, TwoWire *wire = &Wire); bool begin(int8_t writeProtectPin = -1); bool isConnected(); uint8_t getAddress(); // user is responsible that address is in range of the EEPROM used. // writes a byte to memoryAddress // returns I2C status, 0 = OK int writeByte(const uint16_t memoryAddress, const uint8_t value); // writes length bytes from buffer to EEPROM // returns I2C status, 0 = OK int writeBlock(const uint16_t memoryAddress, const uint8_t * buffer, const uint16_t length); // set length bytes in the EEPROM to the same value. // returns I2C status, 0 = OK int setBlock(const uint16_t memoryAddress, const uint8_t value, const uint16_t length); // returns the value stored in memoryAddress uint8_t readByte(const uint16_t memoryAddress); // reads length bytes into buffer // returns bytes read. uint16_t readBlock(const uint16_t memoryAddress, uint8_t * buffer, const uint16_t length); bool verifyBlock(const uint16_t memoryAddress, const uint8_t * buffer, const uint16_t length); // updates a byte at memoryAddress, writes only if there is a new value. // return 0 if data is same or written OK, error code otherwise. int updateByte(const uint16_t memoryAddress, const uint8_t value); // updates a block in memory, writes only if there is a new value. // only to be used when you expect to write same buffer multiple times. // test your performance gains! // returns bytes actually written <= length uint16_t updateBlock(const uint16_t memoryAddress, const uint8_t * buffer, const uint16_t length); // same functions as above but with verify // return false if write or verify failed. bool writeByteVerify(const uint16_t memoryAddress, const uint8_t value); bool writeBlockVerify(const uint16_t memoryAddress, const uint8_t * buffer, const uint16_t length); bool setBlockVerify(const uint16_t memoryAddress, const uint8_t value, const uint16_t length); bool updateByteVerify(const uint16_t memoryAddress, const uint8_t value); bool updateBlockVerify(const uint16_t memoryAddress, const uint8_t * buffer, const uint16_t length); // Meta data functions uint32_t getDeviceSize(); uint8_t getPageSize(); uint8_t calculatePageSize(uint32_t deviceSize); [[deprecated("Use calculatePageSize(deviceSize) instead.")]] uint8_t getPageSize(uint32_t deviceSize); uint32_t determineSizeNoWrite(); uint32_t determineSize(const bool debug = false); uint32_t getLastWrite(); // for overruling and debugging. // forces a power of 2 uint32_t setDeviceSize(uint32_t deviceSize); // returns set size uint8_t setPageSize(uint8_t pageSize); // returns set size // TWR = WriteCycleTime // 5 ms is minimum, one can add extra ms here to adjust timing of both read() and write() void setExtraWriteCycleTime(uint8_t ms); uint8_t getExtraWriteCycleTime(); // WRITEPROTECT // works only if WP pin is defined in begin(). // see readme.md inline bool hasWriteProtectPin(); void allowWrite(); void preventWrite(); void setAutoWriteProtect(bool b); bool getAutoWriteProtect(); private: uint8_t _deviceAddress; uint32_t _lastWrite = 0; // for waitEEReady uint32_t _deviceSize = 0; uint8_t _pageSize = 0; uint8_t _extraTWR = 0; // milliseconds // 24LC32..24LC512 use two bytes for memory address // 24LC01..24LC16 use one-byte addresses + part of device address bool _isAddressSizeTwoWords; void _beginTransmission(const uint16_t memoryAddress); // returns I2C status, 0 = OK // TODO incrBuffer is an implementation name, not a functional name. int _pageBlock(const uint16_t memoryAddress, const uint8_t * buffer, const uint16_t length, const bool incrBuffer); // returns I2C status, 0 = OK int _WriteBlock(const uint16_t memoryAddress, const uint8_t * buffer, const uint16_t length); // returns bytes read. uint8_t _ReadBlock(const uint16_t memoryAddress, uint8_t * buffer, const uint16_t length); // compare bytes in EEPROM. bool _verifyBlock(const uint16_t memoryAddress, const uint8_t * buffer, const uint16_t length); // to optimize the write latency of the EEPROM void _waitEEReady(); TwoWire * _wire; bool _debug = false; int8_t _writeProtectPin = -1; bool _autoWriteProtect = EN_AUTO_WRITE_PROTECT; UNIT_TEST_FRIEND; }; // -- END OF FILE --