Driver library for Microchip I2C EERAM (47x04 and 47x16) 4 kbit or 16 kbit EEPROM backed SRAM.

Dependents:   EERAM_example

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers EERAM.cpp Source File

EERAM.cpp

Go to the documentation of this file.
00001 /**
00002 * @file    EERAM.cpp
00003 * @brief   mbed driver for Microchip I2C EERAM devices (47x04 and 47x16)
00004 * @author  Mark Peter Vargha, vmp@varghamarkpeter.hu
00005 * @version 1.4.0
00006 *
00007 * Copyright (c) 2017
00008 *
00009 * Licensed under the Apache License, Version 2.0 (the "License");
00010 * you may not use this file except in compliance with the License.
00011 * You may obtain a copy of the License at
00012 *
00013 *     http://www.apache.org/licenses/LICENSE-2.0
00014 *
00015 * Unless required by applicable law or agreed to in writing, software
00016 * distributed under the License is distributed on an "AS IS" BASIS,
00017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00018 * See the License for the specific language governing permissions and
00019 * limitations under the License.
00020 */
00021 
00022 #include "EERAM.h"
00023 
00024 void EERAM::initialize(bool A1, bool A2)
00025 {
00026     _sramAddressWrite = OPCODE_SRAM;
00027     _sramAddressWrite ^= (-A1 ^ _sramAddressWrite) & (1 << A1_BIT);
00028     _sramAddressWrite ^= (-A2 ^ _sramAddressWrite) & (1 << A2_BIT);
00029     _sramAddressRead = _sramAddressWrite;
00030     _sramAddressRead ^= (-true ^ _sramAddressRead) & (1 << RW_BIT);
00031 
00032     _controlAddressWrite = OPCODE_CONTROL;
00033     _controlAddressWrite ^= (-A1 ^ _controlAddressWrite) & (1 << A1_BIT);
00034     _controlAddressWrite ^= (-A2 ^ _controlAddressWrite) & (1 << A2_BIT);
00035     _controlAddressRead = _controlAddressWrite;
00036     _controlAddressRead ^= (-true ^ _controlAddressWrite) & (1 << RW_BIT);
00037 }
00038 
00039 void EERAM::putAddressIntoBuffer(uint16_t address, char *data)
00040 {
00041     data[0] = (address >> (8 * 0)) & 0xff;
00042     data[1] = (address >> (8 * 1)) & 0xff;
00043 }
00044 
00045 bool EERAM::checkAddressRange(uint16_t start, uint16_t length)
00046 {
00047     return start < _memorySize && start + length <= _memorySize && length > 0;
00048 }
00049 
00050 bool EERAM::writeBytes(uint16_t address, char *data, int length)
00051 {
00052     bool success = false;
00053     success = checkAddressRange(address, length);
00054     if (success) success = setMemoryPointer(address, false);
00055     int index = 0;
00056     while (index < length && success)
00057     {
00058         success = _i2c.write(data[index]) == 1;
00059         index++;
00060     }
00061     _i2c.stop();
00062     return success;
00063 }
00064 
00065 bool EERAM::writeBytes(char *data, int length)
00066 {
00067     bool success = false;
00068     success = _i2c.write(_sramAddressWrite, data, length) == 0;
00069     return success;
00070 }
00071 
00072 bool EERAM::readBytes(uint16_t address, char *data, int length)
00073 {
00074     bool success = checkAddressRange(address, length);
00075     if (success) success = setMemoryPointer(address, true);
00076     if (success)
00077     {
00078         success = _i2c.read(_sramAddressRead, data, length, false) == 0;
00079     }
00080     _i2c.stop();
00081     return success;
00082 }
00083 
00084 bool EERAM::readBytes(char *data, int length)
00085 {
00086     bool success = setMemoryPointer((uint8_t)data[1], (uint8_t)data[0], true);
00087     if (success)
00088     {
00089         success = _i2c.read(_sramAddressRead, data + 2, length - 2, false) == 0;
00090     }
00091     _i2c.stop();
00092     return success;
00093 }
00094 
00095 bool EERAM::writeRegister(uint8_t registerAddress, uint8_t data)
00096 {
00097     _i2c.start();
00098     bool success = _i2c.write(_controlAddressWrite) == 1;
00099     if (success) success = _i2c.write(registerAddress) == 1;
00100     if (success) success = _i2c.write(data) == 1;
00101     _i2c.stop();
00102     return success;
00103 }
00104 
00105 bool EERAM::store(bool block)
00106 {
00107     bool success = writeRegister(REGISTER_COMMAND, COMMAND_STORE);
00108     if (success && block)
00109     {
00110         isReady((_memorySize <= 512 ? TIME_STORE_04_MS: TIME_STORE_16_MS) * 2);
00111     }
00112     return success;
00113 }
00114 
00115 bool EERAM::recall(bool block)
00116 {
00117     bool success = writeRegister(REGISTER_COMMAND, COMMAND_RECALL);
00118     if (success && block)
00119     {
00120         isReady((_memorySize <= 512 ? TIME_RECALL_04_MS: TIME_RECALL_16_MS) * 2);
00121     }
00122     return success;
00123 }
00124 
00125 bool EERAM::readStatus()
00126 {
00127     _i2c.start();
00128     bool success = _i2c.write(_controlAddressRead) == 1;
00129     if (success)
00130     {
00131         _status = _i2c.read(false);
00132         _statusToWrite = _status;
00133     }
00134     _i2c.stop();
00135     return success;
00136 }
00137 
00138 bool EERAM::writeStatus(bool block)
00139 {
00140     bool success = writeRegister(REGISTER_STATUS, _statusToWrite);
00141     if (success)
00142     {
00143         _status = _statusToWrite;
00144         if (block) isReady(TIME_STORE_STATUS_MS * 2);
00145     }
00146     return success;
00147 }
00148 
00149 void EERAM::writeStatusIfChanged(bool block)
00150 {
00151     if (_statusToWrite != _status) writeStatus(block);
00152 }
00153 
00154 void EERAM::setProtectedMemoryArea(ProtectedMemoryArea protectedMemoryArea, bool store)
00155 {
00156     const uint8_t mask = 0b00011100;
00157     _statusToWrite = (_statusToWrite & ~mask) | ((protectedMemoryArea << 2) & mask);
00158     if (store) writeStatusIfChanged(false);
00159 }
00160 
00161 ProtectedMemoryArea EERAM::getProtectedMemoryArea()
00162 {
00163     return (ProtectedMemoryArea) ((_status >> 2) & ~(-1 << 3));
00164 }
00165 
00166 bool EERAM::isMemoryModified()
00167 {
00168     return (_status >> STATUS_AM_BIT) & 1;
00169 }
00170 
00171 void EERAM::setAutoStoreEnabled(bool enabled, bool store)
00172 {
00173     _statusToWrite ^= (-enabled ^ _statusToWrite) & (1 << STATUS_ASE_BIT);
00174     if (store) writeStatusIfChanged(false);
00175 }
00176 
00177 bool EERAM::isAutoStoreEnabled()
00178 {
00179     return (_status >> STATUS_ASE_BIT) & 1;
00180 }
00181 
00182 void EERAM::setEventDetected(bool detected, bool store)
00183 {
00184     _statusToWrite ^= (-detected ^ _statusToWrite) & (1 << STATUS_EVENT_BIT);
00185     if (store) writeStatusIfChanged(false);
00186 }
00187 
00188 bool EERAM::isEventDetected()
00189 {
00190     return (_status >> STATUS_EVENT_BIT) & 1;
00191 }
00192 
00193 bool EERAM::isReady()
00194 {
00195     bool ready = false;
00196     _i2c.start();
00197     ready = _i2c.write(_controlAddressWrite) == 1;
00198     _i2c.stop();
00199     return ready;
00200 }
00201 
00202 bool EERAM::isReady(int timeout_ms)
00203 {
00204     bool ready = false;
00205     Timer timeoutTimer;
00206     timeoutTimer.start();
00207     while (!ready && timeoutTimer.read_ms() < timeout_ms)
00208     {
00209         ready = isReady();
00210         if (ready)
00211         {
00212             break;
00213         }
00214     }
00215     return ready;
00216 }
00217 
00218 void EERAM::dump(Serial &serial, uint16_t start, uint16_t length, int lineSize)
00219 {
00220     const int lineMaxSize = 32;
00221     if (!checkAddressRange(start, length) || lineSize > lineMaxSize)
00222     {
00223         serial.printf("Invalid parameters for memory dump.\r\n");
00224         return;
00225     }
00226     if (!setMemoryPointer(start, true))
00227     {
00228         serial.printf("Could not set start address for memory dump.\r\n");
00229         return;
00230     }
00231     char buffer[lineMaxSize];
00232     int lastLineLength = length % lineSize;
00233     int segments = length / lineSize + (lastLineLength > 0 ? 1 : 0);
00234     lastLineLength = lastLineLength == 0 ? lineSize : lastLineLength;
00235     for (int i = 0; i < segments; i++)
00236     {
00237         serial.printf("%.4X", start + lineSize * i);
00238         _i2c.read(_sramAddressRead, buffer, lineSize, false);
00239         for (int j = 0; j < (i == segments - 1 ? lastLineLength : lineSize); j++)
00240         {
00241             serial.printf(" %.2X", buffer[j]);
00242         }
00243         serial.printf("\r\n");
00244     }
00245 }
00246 
00247 void EERAM::dump(Serial &serial)
00248 {
00249     dump(serial, 0, _memorySize);
00250 }
00251 
00252 bool EERAM::setMemoryPointer(uint16_t address, bool stop)
00253 {
00254     return setMemoryPointer((address >> (8 * 1)) & 0xff, (address >> (8 * 0)) & 0xff, stop);
00255 }
00256 
00257 bool EERAM::setMemoryPointer(uint8_t address_0, uint8_t address_1, bool stop)
00258 {
00259     int result = 0;
00260     _i2c.start();
00261     result = _i2c.write(_sramAddressWrite);
00262     if (result == 1) result = _i2c.write(address_1);
00263     if (result == 1) result = _i2c.write(address_0);
00264     if (stop) _i2c.stop();
00265     return result == 1;
00266 }
00267 
00268 bool EERAM::fillMemory(uint16_t address, char data, int length)
00269 {
00270     int result = 0;
00271     result = setMemoryPointer(address, false) ? 1 : 0;
00272     int index = 0;
00273     while (index < length && result == 1)
00274     {
00275         result = _i2c.write(data);
00276         index++;
00277     }
00278     _i2c.stop();
00279     return result == 1;
00280 }
00281 
00282 bool EERAM::fillMemory(char data)
00283 {
00284     return fillMemory(0, data, _memorySize);
00285 }
00286 
00287 void EERAM::dumpRegisters(Serial &serial)
00288 {
00289     serial.printf("Status Register Contents\r\n");
00290     serial.printf("Event detected: %d\r\n", isEventDetected());
00291     serial.printf("Auto Store Enabled: %d\r\n", isAutoStoreEnabled());
00292     serial.printf("Protected area: %d = ", getProtectedMemoryArea());
00293     switch (getProtectedMemoryArea())
00294     {
00295     case NONE:
00296         serial.printf("None");
00297         break;
00298     case U64:
00299         serial.printf("U64");
00300         break;
00301     case U32:
00302         serial.printf("U32");
00303         break;
00304     case U16:
00305         serial.printf("U16");
00306         break;
00307     case U8:
00308         serial.printf("U8");
00309         break;
00310     case U4:
00311         serial.printf("U4");
00312         break;
00313     case U2:
00314         serial.printf("U2");
00315         break;
00316     case ALL:
00317         serial.printf("All");
00318         break;
00319     }
00320     serial.printf("\r\n");
00321     serial.printf("Memory Array Modified: %d\r\n", isMemoryModified());
00322 }