mFS file system library for EEPROM memory chips.

i2c_eeprom.cpp

Committer:
HBP
Date:
2011-02-24
Revision:
13:142b6be3e3c8
Parent:
9:52c01cb100ac

File content as of revision 13:142b6be3e3c8:

/** @file i2c_eeprom.cpp */
/*CPP**************************************************************************
 * FILENAME :        i2c_eeprom.cpp                                           *
 *                                                                            *
 * DESCRIPTION :                                                              *
 *       Simple library for external I2C EEEPROM.                             *
 *                                                                            *
 * AUTHOR :    Olli Vanhoja        START DATE :    2011-02-17                 *
 *****************************************************************************/

#include "mbed.h"
#include "i2c_eeprom.h"

I2C i2c(p28, p27); /**< I2C */
DigitalOut BusyLed(LED1);  /**< Busy led */
DigitalInOut scl_ext(p20); /**< \attention Clock override pin connected to SCL */

i2c_eeprom::i2c_eeprom(int hwAddr, int speed)
{
    i_i2c_address = hwAddr;
    
    scl_ext.input();      // Make it input to start with...
    scl_ext.mode(PullUp); // ...with pull up
        
    i2c.frequency(speed);
}

void i2c_eeprom::write(char *data, uint16_t iAddr, unsigned int n)
{
    char *pi2c_data[3]; // Pointers for CW items
    char i2c_data[3];   // Final CW
    
    BusyLed = 1;

    /* Convert address to hi and low byte array
     * This is really pointless even though they are
     * called pointers it would be lot easier to do this
     * conversion without any pointers */
    uint16_t *piAddr = &iAddr;
    pi2c_data[0] = (char *)piAddr+1;
    pi2c_data[1] = (char *)piAddr;
    
    for (uint16_t i=0; i < n; i++)
    {
        pi2c_data[2] = &data[i];
        
        // Apply actual values from pointer
        //for (int n=0; n < 3; n++)
        //    i2c_data[n] = *pi2c_data[n];
        i2c_data[0] = *pi2c_data[0];
        i2c_data[1] = *pi2c_data[1];
        i2c_data[2] = *pi2c_data[2];
        
        // Send write command
        strwrite:
        if(i2c.write(i_i2c_address, i2c_data, 3))
        {
            autoreset();
            goto strwrite;
        }
        
        iAddr++; // increment address counter

        // Wait for ACK        
        while(i2c.write(i_i2c_address, NULL, 0)){}
    }
    
    BusyLed = 0;
}

void i2c_eeprom::read(uint16_t iAddr, uint16_t n, char *out)
{
    char *pi2c_data[2]; // Pointers for CW items
    char i2c_data[2];   // Final CW
    
    uint16_t *piAddr = &iAddr;
    pi2c_data[0] = (char *)piAddr+1;
    pi2c_data[1] = (char *)piAddr;
    
    BusyLed = 1;
    
    // Apply actual values from pointer
    //for (int i=0; i < 2; i++)
    //    i2c_data[i] = *pi2c_data[i];
    i2c_data[0] = *pi2c_data[0];
    i2c_data[1] = *pi2c_data[1];
    
    // Send read command
    strread:
    if(i2c.write(i_i2c_address, i2c_data, 2))
    {
        autoreset();
        goto strread;
    }
    
    if(i2c.read(i_i2c_address, out, n))
    {
        autoreset();
        goto strread;
    }
    
    BusyLed = 0;
}

void i2c_eeprom::autoreset()
{
    i2c.start();
    scl_ext = 0;          // Setup override pin to pull clock low
    scl_ext.input();      // Make it input to start with...
    scl_ext.mode(PullUp); // ...with pull up
    wait(0.00005);        // Pause after stop
    scl_ext.output();     // Override clock pin low
    wait(0.00005);        // Pause
    scl_ext.input();      // Remove override...
    scl_ext.mode(PullUp); // ...with pull up
    wait(0.00005);        // Pause again
    i2c.start();
    i2c.stop();
}