Mark Peter Vargha / EERAM

Dependents:   EERAM_example

Files at this revision

API Documentation at this revision

Comitter:
vargham
Date:
Tue Apr 25 15:05:37 2017 +0000
Child:
1:6028bc22d82f
Commit message:
EERAM initial commit

Changed in this revision

EERAM.cpp Show annotated file Show diff for this revision Revisions of this file
EERAM.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/EERAM.cpp	Tue Apr 25 15:05:37 2017 +0000
@@ -0,0 +1,144 @@
+/**
+* @file    eeram_main.cpp
+* @brief   Example program for Microchip I2C EERAM devices (47x04 and 47x16)
+* @author  Mark Peter Vargha, vmp@varghamarkpeter.hu
+* @version 1.0.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 "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 printI2C()
+{
+    //0x41  Discovery Touch
+    //0x18  EERAM control
+    //0x50  EERAM memory
+
+    int error;
+    int address;
+    int nDevices = 0;
+
+    serial.printf("Scanning I2C devices...\r\n");
+
+    for(address = 1; address < 127; address++ )
+    {
+        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++;
+        }
+
+    }
+    serial.printf("I2C scan finished.\r\n");
+    if (nDevices == 0)
+    {
+        serial.printf("No I2C devices found.\r\n");
+    }
+
+}
+
+void fillTestData(char data[], uint8_t start, int length)
+{
+    for (int i = 0; i < length; i++) data[i] = start + i;
+}
+
+void eeramDataTest()
+{
+    const int testDataLength = 16;
+    char data[testDataLength];
+
+    //Write
+    //eeram.fillMemory(0xFF);
+
+    fillTestData(data, 0x0, testDataLength);
+    serial.printf("Write %d bytes to 0x0: %d\r\n", testDataLength, eeram.write(0x0, data, testDataLength));
+
+    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));
+
+    //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");
+
+    //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++)
+    {
+        serial.printf("%.2X ", data[i]);
+    }
+    serial.printf("\r\n");
+}
+
+void eeramRegisterTest()
+{
+    eeram.dumpRegisters(serial);
+}
+
+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)
+    {
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/EERAM.h	Tue Apr 25 15:05:37 2017 +0000
@@ -0,0 +1,315 @@
+/**
+* @file    EERAM.h
+* @brief   mbed driver for Microchip I2C EERAM devices (47x04 and 47x16)
+* @author  Mark Peter Vargha, vmp@varghamarkpeter.hu
+* @version 1.0.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.
+*/
+
+#ifndef EERAM_h
+#define EERAM_h
+
+#include "mbed.h"
+
+//#define DEBUG_EERAM
+
+#ifdef DEBUG_EERAM
+extern Serial serial;
+#endif
+
+union MemoryAddress
+{
+    uint16_t address;
+    char bytes[2];
+};
+
+enum ProtectedMemoryArea
+{
+    NONE = 0, U64, U32, U16, U8, U4, U2, ALL
+};
+
+/** An I2C EERAM interface to communicate with Microchip 47x04 and 47x16 devices
+* 4 kbit (512 byte) or 16 kbit (2048 byte) EEPROM backed I2C SRAM
+* The device could detect power down and stores SRAM contents in EEPROM. The SRAM is recalled from EEPROM on power up.
+*
+* <a href="http://ww1.microchip.com/downloads/en/DeviceDoc/20005371C.pdf">47x04 and 47x16 datasheet</a>
+* <a href="http://ww1.microchip.com/downloads/cn/AppNotes/cn588417.pdf">Recommended Usage of Microchip I2C EERAM Devices</a>
+* <a href="http://ww1.microchip.com/downloads/en/AppNotes/00002257A.pdf">Choosing the Right EERAM VCAP Capacitor</a>
+*
+* Example:
+* @code
+#include "mbed.h"
+#include "EERAM.h"
+
+EERAM eeram(I2C_SDA, I2C_SCL, 2048);
+
+int main()
+{
+    if (!eeram.isReady(100)) //Checks device with 100 ms timeout
+    {
+        printf("Device is not present.");
+        while (1);
+    }
+    eeram.readStatus(); //Reads status register
+    eeram.setAutoStoreEnabled(true, true); //Set auto store on power down to true and stores if not stored before
+    while (1)
+    {
+        char dataStore[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
+        eeram.write(0x100, dataStore, 16); //We can not wear EEPROM out, so it is ok to write data to the device frequently.
+        wait(2.0);
+        char dataRead[16];
+        eeram.read(0x100, dataRead, 16);
+        wait(2.0);
+    }
+}
+
+* @endcode
+*/
+class EERAM
+{
+
+public:
+
+    /** Create an I2C EERAM interface, connected to the specified pins, with specified size and with the specified address pins
+    * @param SDA I2C data line pin
+    * @param SCL I2C clock line pin
+    * @param memorySize Size of EERAM, 512 for 47x04 and 2048 for 47x16
+    * @param A1 EERAM A1 pin state (true = high, false = low)
+    * @param A2 EERAM A2 pin state (true = high, false = low)
+    */
+    EERAM(PinName SDA, PinName SCL, uint16_t memorySize, bool A1 = false, bool A2 = false) :
+        _i2c(SDA, SCL),
+        _memorySize(memorySize)
+    {
+        initialize(A1, A2);
+    };
+
+    /** Create an I2C EERAM interface, connected to the I2C, with specified size and with the specified address pins
+    * @param 12c I2C
+    * @param memorySize Size of EERAM, 512 for 47x04 and 2048 for 47x16
+    * @param A1 EERAM A1 pin state (true = high, false = low)
+    * @param A2 EERAM A2 pin state (true = high, false = low)
+    */
+    EERAM(I2C &i2c, uint16_t memorySize, bool A1 = false, bool A2 = false) :
+        _i2c(i2c),
+        _memorySize(memorySize)
+    {
+        initialize(A1, A2);
+    };
+
+    /** Writes data to the specified address
+    * @param address The 16 bit destination address
+    * @param data Pointer to the data buffer to read from
+    * @param length Data length
+    *
+    * @return
+    *   true on success
+    *   false on fail
+    */
+    bool write(uint16_t address, char *data, int length);
+
+    /** Reads data from the specified address
+    * @param address The 16 bit source address
+    * @param data Pointer to the data buffer to read to
+    * @param length Data length
+    *
+    * @return
+    *   true on success
+    *   false on fail
+    */
+    bool read(uint16_t address, char *data, int length);
+
+    /** Fills memory with the specified byte from the specified address
+    * @param address The 16 bit destination address
+    * @param data The byte to write
+    * @param length Memory are to fill with the data byte
+    *
+    * @return
+    *   true on success
+    *   false on fail
+    */
+    bool fillMemory(uint16_t address, char data, int length);
+
+    /** Fills the whole memory with the specified byte
+    * @param data The byte to write
+    *
+    * @return
+    *   true on success
+    *   false on fail
+    */
+    bool fillMemory(char data);
+
+    /** Continuously checks I2C EERAM device till ready or reaches timeout
+    * @param timeout_ms Timeout for busy-wait I2C device polling
+    *
+    * @return
+    *   true on ready
+    *   false on timeout
+    */
+    bool isReady(int timeout_ms);
+
+    /** Checks I2C EERAM device one time
+    *
+    * @return
+    *   true on ready
+    *   false on not ready
+    */
+    bool isReady();
+
+    /** Store SRAM in EEPROM
+    * @param block If true, busy waits for operation end.
+    *
+    * @return
+    *   true on success
+    *   false on fail
+    */
+    bool store(bool block);
+
+    /** Recall SRAM from EEPROM
+    * @param block If true, busy waits for operation end.
+    *
+    * @return
+    *   true on success
+    *   false on fail
+    */
+    bool recall(bool block);
+
+    /** Reads status register
+    *
+    * @return
+    *   true on success
+    *   false on fail
+    */
+    bool readStatus();
+
+    /** Gets status register
+    *
+    * @return The content of the 8 bit status register
+    */
+    inline uint8_t getStatus() const
+    {
+        return _status;
+    }
+
+    /** Writes the 8 bit status register to the I2C device
+    * @param block If true, busy waits for operation end.
+    *
+    * @return
+    *   true on success
+    *   false on fail
+    */
+    bool writeStatus(bool block);
+
+    /** Writes the 8 bit status register to the I2C device if changed
+    * @param block If true, busy waits for operation end.
+    */
+    void writeStatusIfChanged(bool block);
+
+    /** Sets protected memory area. The selected area will be write protected.
+    * @param protectedMemoryArea The enum represents the area from NONE through upper 64, 32, 16, 8, 4, 2 to ALL
+    * @param store If true, calls writeStatusIfChanged()
+    */
+    void setProtectedMemoryArea(ProtectedMemoryArea protectedMemoryArea, bool store = false);
+
+    /** Gets protected memory area
+    *   Have to call readStatus() to read register's fresh value.
+    */
+    ProtectedMemoryArea getProtectedMemoryArea();
+
+    /** Gets Memory Modified
+    *   Have to call readStatus() to read register's fresh value.
+    * @return
+    *   true The SRAM memory have been modified since the last store or recall operation
+    *   false The SRAM memory have not been modified since the last store or recall operation
+    */
+    bool isMemoryModified();
+
+    /** Sets Auto Store Enabled
+    * @param enabled Auto store SRAM to EEPROM on power down enabled
+    * @param store If true, calls writeStatusIfChanged()
+    */
+    void setAutoStoreEnabled(bool enabled, bool store = false);
+
+    /** Gets Auto Store Enabled
+    *   Have to call readStatus() to read register's fresh value.
+    * @return
+    *   true Auto Store is Enabled
+    *   false Auto Store is not Enabled
+    */
+    bool isAutoStoreEnabled();
+
+    /** Sets event detected
+    * @param detected The value of the detected bit
+    * @param store If true, calls writeStatusIfChanged()
+    */
+    void setEventDetected(bool detected, bool store);
+
+    /** Gets event detected
+    *   Have to call readStatus() to read register's fresh value.
+    * @return
+    *   true External store event detected (The HS pin pulled up)
+    *   false External event not detected
+    */
+    bool isEventDetected();
+
+    /** Prints the SRAM content from the given address to the given serial port in human readable format in 1-32 byte long lines
+    * @param serial The port to print to
+    */
+    void dump(Serial &serial, uint16_t start, uint16_t length, int lineSize = 16);
+
+    /** Prints the whole SRAM content to the given serial port in human readable format in 16 byte long lines
+    * @param serial The port to print to
+    */
+    void dump(Serial &serial);
+
+    /** Prints the 8 bit status register's contents to the given serial port in human readable format
+    * @param serial The port to print to
+    */
+    void dumpRegisters(Serial &serial);
+
+private:
+    static const uint8_t RW_BIT = 0;
+    static const uint8_t A1_BIT = 2;
+    static const uint8_t A2_BIT = 3;
+    static const uint8_t STATUS_AM_BIT = 7;
+    static const uint8_t STATUS_ASE_BIT = 1;
+    static const uint8_t STATUS_EVENT_BIT = 0;
+    static const uint8_t OPCODE_SRAM = 0b10100000;
+    static const uint8_t OPCODE_CONTROL = 0b00110000;
+    static const uint8_t REGISTER_STATUS = 0x0;
+    static const uint8_t REGISTER_COMMAND = 0x55;
+    static const uint8_t COMMAND_STORE = 0b00110011;
+    static const uint8_t COMMAND_RECALL = 0b11011101;
+    static const int TIME_RECALL_16_MS = 5;
+    static const int TIME_RECALL_04_MS = 2;
+    static const int TIME_STORE_16_MS = 25;
+    static const int TIME_STORE_04_MS = 8;
+    static const int TIME_STORE_STATUS_MS = 1;
+    I2C _i2c;
+    uint16_t _memorySize;
+    uint8_t _sramAddressWrite;
+    uint8_t _sramAddressRead;
+    uint8_t _controlAddressWrite;
+    uint8_t _controlAddressRead;
+    uint8_t _status;
+    uint8_t _statusToWrite;
+    void initialize(bool A1 = false, bool A2 = false);
+    bool checkAddressRange(uint16_t start, uint16_t length);
+    bool writeRegister(uint8_t registerAddress, uint8_t data);
+    bool setMemoryPointer(uint16_t address, bool stop = true);
+};
+
+#endif //EERAM_h