Driver library for Microchip I2C EERAM (47x04 and 47x16) 4 kbit or 16 kbit EEPROM backed SRAM.
Diff: EERAM.cpp
- Revision:
- 1:6028bc22d82f
- Parent:
- 0:19f9af07424a
- Child:
- 2:bdbf9de0e985
diff -r 19f9af07424a -r 6028bc22d82f EERAM.cpp --- a/EERAM.cpp Tue Apr 25 15:05:37 2017 +0000 +++ b/EERAM.cpp Tue Apr 25 16:22:53 2017 +0000 @@ -1,6 +1,6 @@ /** -* @file eeram_main.cpp -* @brief Example program for Microchip I2C EERAM devices (47x04 and 47x16) +* @file EERAM.cpp +* @brief mbed driver for Microchip I2C EERAM devices (47x04 and 47x16) * @author Mark Peter Vargha, vmp@varghamarkpeter.hu * @version 1.0.0 * @@ -19,126 +19,277 @@ * limitations under the License. */ -#include "mbed.h" #include "EERAM.h" -#define PIN_I2C_SDA PC_9 -#define PIN_I2C_SCL PA_8 - -#define I2C_FREQUENCY 1000000 - -Serial serial(PA_9, PA_10); //Tx, Rx -I2C i2c(PIN_I2C_SDA, PIN_I2C_SCL); //SDA, SCL -EERAM eeram(i2c, 2048); +void EERAM::initialize(bool A1, bool A2) +{ + _sramAddressWrite = OPCODE_SRAM; + _sramAddressWrite ^= (-A1 ^ _sramAddressWrite) & (1 << A1_BIT); + _sramAddressWrite ^= (-A2 ^ _sramAddressWrite) & (1 << A2_BIT); + _sramAddressRead = _sramAddressWrite; + _sramAddressRead ^= (-true ^ _sramAddressRead) & (1 << RW_BIT); -void printI2C() + _controlAddressWrite = OPCODE_CONTROL; + _controlAddressWrite ^= (-A1 ^ _controlAddressWrite) & (1 << A1_BIT); + _controlAddressWrite ^= (-A2 ^ _controlAddressWrite) & (1 << A2_BIT); + _controlAddressRead = _controlAddressWrite; + _controlAddressRead ^= (-true ^ _controlAddressWrite) & (1 << RW_BIT); +} + +bool EERAM::checkAddressRange(uint16_t start, uint16_t length) { - //0x41 Discovery Touch - //0x18 EERAM control - //0x50 EERAM memory - - int error; - int address; - int nDevices = 0; + return start < _memorySize && start + length <= _memorySize && length > 0; +} - serial.printf("Scanning I2C devices...\r\n"); - - for(address = 1; address < 127; address++ ) +bool EERAM::write(uint16_t address, char *data, int length) +{ + bool success = false; + success = checkAddressRange(address, length); + if (success) success = setMemoryPointer(address, false); + int index = 0; + while (index < length && success) { - i2c.start(); - error = i2c.write(address << 1); //We shift it left because mbed takes in 8 bit addreses - i2c.stop(); - if (error == 1) - { - serial.printf("I2C device found at address 0x%X\r\n", address); //Returns 7-bit addres - nDevices++; - } + success = _i2c.write(data[index]) == 1; + index++; + } + _i2c.stop(); + return success; +} - } - serial.printf("I2C scan finished.\r\n"); - if (nDevices == 0) +bool EERAM::read(uint16_t address, char *data, int length) +{ + bool success = checkAddressRange(address, length); + if (success) success = setMemoryPointer(address, true); + if (success) { - serial.printf("No I2C devices found.\r\n"); + success = _i2c.read(_sramAddressRead, data, length, false) == 0; } + _i2c.stop(); + return success; +} +bool EERAM::writeRegister(uint8_t registerAddress, uint8_t data) +{ + _i2c.start(); + bool success = _i2c.write(_controlAddressWrite) == 1; + if (success) success = _i2c.write(registerAddress) == 1; + if (success) success = _i2c.write(data) == 1; + _i2c.stop(); + return success; } -void fillTestData(char data[], uint8_t start, int length) +bool EERAM::store(bool block) +{ + bool success = writeRegister(REGISTER_COMMAND, COMMAND_STORE); + if (success && block) + { + isReady((_memorySize <= 512 ? TIME_STORE_04_MS: TIME_STORE_16_MS) * 2); + } + return success; +} + +bool EERAM::recall(bool block) +{ + bool success = writeRegister(REGISTER_COMMAND, COMMAND_RECALL); + if (success && block) + { + isReady((_memorySize <= 512 ? TIME_RECALL_04_MS: TIME_RECALL_16_MS) * 2); + } + return success; +} + +bool EERAM::readStatus() +{ + _i2c.start(); + bool success = _i2c.write(_controlAddressRead) == 1; + if (success) + { + _status = _i2c.read(false); + _statusToWrite = _status; + } + _i2c.stop(); + return success; +} + +bool EERAM::writeStatus(bool block) { - for (int i = 0; i < length; i++) data[i] = start + i; + bool success = writeRegister(REGISTER_STATUS, _statusToWrite); + if (success) + { + _status = _statusToWrite; + if (block) isReady(TIME_STORE_STATUS_MS * 2); + } + return success; +} + +void EERAM::writeStatusIfChanged(bool block) +{ + if (_statusToWrite != _status) writeStatus(block); +} + +void EERAM::setProtectedMemoryArea(ProtectedMemoryArea protectedMemoryArea, bool store) +{ + const uint8_t mask = 0b00011100; + _statusToWrite = (_statusToWrite & ~mask) | ((protectedMemoryArea << 2) & mask); + if (store) writeStatusIfChanged(false); +} + +ProtectedMemoryArea EERAM::getProtectedMemoryArea() +{ + return (ProtectedMemoryArea) ((_status >> 2) & ~(-1 << 3)); +} + +bool EERAM::isMemoryModified() +{ + return (_status >> STATUS_AM_BIT) & 1; +} + +void EERAM::setAutoStoreEnabled(bool enabled, bool store) +{ + _statusToWrite ^= (-enabled ^ _statusToWrite) & (1 << STATUS_ASE_BIT); + if (store) writeStatusIfChanged(false); +} + +bool EERAM::isAutoStoreEnabled() +{ + return (_status >> STATUS_ASE_BIT) & 1; } -void eeramDataTest() +void EERAM::setEventDetected(bool detected, bool store) +{ + _statusToWrite ^= (-detected ^ _statusToWrite) & (1 << STATUS_EVENT_BIT); + if (store) writeStatusIfChanged(false); +} + +bool EERAM::isEventDetected() { - const int testDataLength = 16; - char data[testDataLength]; + return (_status >> STATUS_EVENT_BIT) & 1; +} - //Write - //eeram.fillMemory(0xFF); +bool EERAM::isReady() +{ + bool ready = false; + _i2c.start(); + ready = _i2c.write(_controlAddressWrite) == 1; + _i2c.stop(); + return ready; +} - fillTestData(data, 0x0, testDataLength); - serial.printf("Write %d bytes to 0x0: %d\r\n", testDataLength, eeram.write(0x0, data, testDataLength)); +bool EERAM::isReady(int timeout_ms) +{ + bool ready = false; + Timer timeoutTimer; + timeoutTimer.start(); + while (!ready && timeoutTimer.read_ms() < timeout_ms) + { + ready = isReady(); + if (ready) + { + break; + } + } + return ready; +} - fillTestData(data, 0x50, testDataLength); - serial.printf("Write %d bytes to 0x500: %d\r\n", testDataLength, eeram.write(0x500, data, testDataLength)); - - fillTestData(data, 0x70, testDataLength); - serial.printf("Write %d bytes to 0x700: %d\r\n", testDataLength, eeram.write(0x700, data, testDataLength)); +void EERAM::dump(Serial &serial, uint16_t start, uint16_t length, int lineSize) +{ + const int lineMaxSize = 32; + if (!checkAddressRange(start, length) || lineSize > lineMaxSize) + { + serial.printf("Invalid parameters for memory dump.\r\n"); + return; + } + if (!setMemoryPointer(start, true)) + { + serial.printf("Could not set start address for memory dump.\r\n"); + return; + } + char buffer[lineMaxSize]; + int lastLineLength = length % lineSize; + int segments = length / lineSize + (lastLineLength > 0 ? 1 : 0); + lastLineLength = lastLineLength == 0 ? lineSize : lastLineLength; + for (int i = 0; i < segments; i++) + { + serial.printf("%.4X", start + lineSize * i); + _i2c.read(_sramAddressRead, buffer, lineSize, false); + for (int j = 0; j < (i == segments - 1 ? lastLineLength : lineSize); j++) + { + serial.printf(" %.2X", buffer[j]); + } + serial.printf("\r\n"); + } +} - //Dump - serial.printf("Dump contents 0x0, 16\r\n"); - eeram.dump(serial, 0x0, testDataLength); - serial.printf("Dump contents 0x500, 16\r\n"); - eeram.dump(serial, 0x500, testDataLength); - serial.printf("Dump contents 0x700, 16\r\n"); - eeram.dump(serial, 0x700, testDataLength); - //serial.printf("Dump all\r\n"); - //eeram.dump(serial); - serial.printf("Dump done\r\n"); +void EERAM::dump(Serial &serial) +{ + dump(serial, 0, _memorySize); +} + +bool EERAM::setMemoryPointer(uint16_t address, bool stop) +{ + int result = 0; + MemoryAddress location; + location.address = address; + _i2c.start(); + result = _i2c.write(_sramAddressWrite); + if (result == 1) result = _i2c.write(location.bytes[1]); + if (result == 1) result = _i2c.write(location.bytes[0]); + if (stop) _i2c.stop(); + return result == 1; +} + +bool EERAM::fillMemory(uint16_t address, char data, int length) +{ + int result = 0; + result = setMemoryPointer(address, false) ? 1 : 0; + int index = 0; + while (index < length && result == 1) + { + result = _i2c.write(data); + index++; + } + _i2c.stop(); + return result == 1; +} - //Read back - fillTestData(data, 0x0, testDataLength); - serial.printf("Read back 16 bytes from 0x500: %d\r\n", eeram.read(0x500, data, testDataLength)); - serial.printf("%.4X ", 0x500); - for (int i = 0; i < testDataLength; i++) +bool EERAM::fillMemory(char data) +{ + return fillMemory(0, data, _memorySize); +} + +void EERAM::dumpRegisters(Serial &serial) +{ + serial.printf("Control Register Contents\r\n"); + serial.printf("Event detected: %d\r\n", isEventDetected()); + serial.printf("Auto Store Enabled: %d\r\n", isAutoStoreEnabled()); + serial.printf("Protected area: %d = ", getProtectedMemoryArea()); + switch (getProtectedMemoryArea()) { - serial.printf("%.2X ", data[i]); + case NONE: + serial.printf("None"); + break; + case U64: + serial.printf("U64"); + break; + case U32: + serial.printf("U32"); + break; + case U16: + serial.printf("U16"); + break; + case U8: + serial.printf("U8"); + break; + case U4: + serial.printf("U4"); + break; + case U2: + serial.printf("U2"); + break; + case ALL: + serial.printf("All"); + break; } serial.printf("\r\n"); -} - -void eeramRegisterTest() -{ - eeram.dumpRegisters(serial); + serial.printf("Memory Array Modified: %d\r\n", isMemoryModified()); } - -int main() -{ - serial.baud(460800); - i2c.frequency(I2C_FREQUENCY); //Hz - serial.printf("\r\nI2C EERAM example\r\n"); - - //printI2C(); - - serial.printf("Is EERAM device ready?\r\n"); - while (!eeram.isReady()); - serial.printf("Device is ready.\r\n"); - - eeram.readStatus(); - eeram.setAutoStoreEnabled(true); - eeram.setProtectedMemoryArea(U64); - eeram.writeStatusIfChanged(true); - serial.printf("Status: %.2X\r\n", eeram.getStatus()); - - eeramDataTest(); - - eeramRegisterTest(); - - //eeram.store(true); - //eeram.recall(true); - - while (true) - { - - } -}