Driver library for Microchip I2C EERAM (47x04 and 47x16) 4 kbit or 16 kbit EEPROM backed SRAM.
EERAM.cpp
- Committer:
- vargham
- Date:
- 2017-04-27
- Revision:
- 3:a869096d7a5d
- Parent:
- 2:bdbf9de0e985
- Child:
- 4:fd84e2f0d1de
File content as of revision 3:a869096d7a5d:
/** * @file EERAM.cpp * @brief mbed driver for Microchip I2C EERAM devices (47x04 and 47x16) * @author Mark Peter Vargha, vmp@varghamarkpeter.hu * @version 1.2.0 * * Copyright (c) 2017 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "EERAM.h" 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); _controlAddressWrite = OPCODE_CONTROL; _controlAddressWrite ^= (-A1 ^ _controlAddressWrite) & (1 << A1_BIT); _controlAddressWrite ^= (-A2 ^ _controlAddressWrite) & (1 << A2_BIT); _controlAddressRead = _controlAddressWrite; _controlAddressRead ^= (-true ^ _controlAddressWrite) & (1 << RW_BIT); } void EERAM::putAddressIntoBuffer(uint16_t address, char *data) { MemoryAddress location; location.address = address; data[0] = location.bytes[1]; data[1] = location.bytes[0]; } bool EERAM::checkAddressRange(uint16_t start, uint16_t length) { return start < _memorySize && start + length <= _memorySize && length > 0; } 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) { success = _i2c.write(data[index]) == 1; index++; } _i2c.stop(); return success; } bool EERAM::write(char *data, int length) { bool success = false; success = _i2c.write(_sramAddressWrite, data, length) == 0; return success; } bool EERAM::read(uint16_t address, char *data, int length) { bool success = checkAddressRange(address, length); if (success) success = setMemoryPointer(address, true); if (success) { success = _i2c.read(_sramAddressRead, data, length, false) == 0; } _i2c.stop(); return success; } bool EERAM::read(char *data, int length) { bool success = setMemoryPointer((uint8_t)data[1], (uint8_t)data[0], true); if (success) { success = _i2c.read(_sramAddressRead, data + 2, length - 2, 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; } 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) { 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 EERAM::setEventDetected(bool detected, bool store) { _statusToWrite ^= (-detected ^ _statusToWrite) & (1 << STATUS_EVENT_BIT); if (store) writeStatusIfChanged(false); } bool EERAM::isEventDetected() { return (_status >> STATUS_EVENT_BIT) & 1; } bool EERAM::isReady() { bool ready = false; _i2c.start(); ready = _i2c.write(_controlAddressWrite) == 1; _i2c.stop(); return ready; } 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; } 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"); } } void EERAM::dump(Serial &serial) { dump(serial, 0, _memorySize); } bool EERAM::setMemoryPointer(uint16_t address, bool stop) { MemoryAddress location; location.address = address; return setMemoryPointer(location.bytes[0], location.bytes[1], stop); } bool EERAM::setMemoryPointer(uint8_t address_0, uint8_t address_1, bool stop) { int result = 0; _i2c.start(); result = _i2c.write(_sramAddressWrite); if (result == 1) result = _i2c.write(address_1); if (result == 1) result = _i2c.write(address_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; } bool EERAM::fillMemory(char data) { return fillMemory(0, data, _memorySize); } void EERAM::dumpRegisters(Serial &serial) { serial.printf("Status 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()) { 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"); serial.printf("Memory Array Modified: %d\r\n", isMemoryModified()); }