EEPROM with 64kByte Memory

AT24C64D.cpp

Committer:
x1dmoesc
Date:
2019-03-05
Revision:
4:660801ce718c
Parent:
3:8a0bfc787463

File content as of revision 4:660801ce718c:

#include "AT24C64D.h"
#include "math.h"



//******************************************************************************//
// uiAddr:   user address [A2...A0]
//******************************************************************************//
AT24C64D::AT24C64D(I2C *_i2c, uint8_t uiAddr)                            //
    :   AT24C64D_W( HARD_ADDR| (uiAddr & USER_ADDR_MASK) << 1),               // Initialisation of const WRITE
        AT24C64D_R( AT24C64D_W | 0x01 ){
        
        
        printf("Contructor of EEPROM AT24C64D...");
        bAck = NACK;
        timer = new Timer;
        startTimer();
        
        i2c = _i2c;
        
        for(int a; a <= SIZE_PAGE; a++)
            cBuffer[a] = 0x00;
        
        printf("end\n");
        
        uiAddrWrite = 0;
        uiAddrRead  = 0;
}


//******************************************************************************//
//  Returns the address of the spi bus. This is the combination of the Hardware //
//  chip address and the user defined addres [A2..A0]                           //
//******************************************************************************//
uint8_t AT24C64D::getAddrBus(){
    return AT24C64D_W;
}



//******************************************************************************//
//  Returns the user defined address [A2..A0]                                   //
//******************************************************************************//
uint8_t AT24C64D::getAddrUser(){
    return (AT24C64D_W >> 1) & USER_ADDR_MASK;
}

//******************************************************************************//
//  Sets the address for the writing position. If the address is higher as the  //
//  max. memory address, then the writing address will be 0x00.                 //
//******************************************************************************//
void AT24C64D::setAddrWrite(uint16_t Addr){    
    if(uiAddrWrite > MEM_ADDR_MAX)  uiAddrWrite = 0;
    else                            uiAddrWrite = Addr;

}


//******************************************************************************//
// Increments the writing address. If the address is higher as the max. memory  //
// adress, it will be roll over.                                                //
//******************************************************************************//
void AT24C64D::incAddrWrite(){
    if(uiAddrWrite >= MEM_ADDR_MAX) uiAddrWrite = 0;
    else                            uiAddrWrite++;
}



//******************************************************************************//
// Decrements the writing address. If the address is smaller or equals to zero, //
// it will be roll over.                                                        //
//******************************************************************************//
void AT24C64D::decAddrWrite(){
    if(uiAddrWrite <= 0)            uiAddrWrite = 4095;
    else                            uiAddrRead--;
}



//******************************************************************************//
// Returns the current writing address.                                         //
//******************************************************************************//
uint16_t AT24C64D::getAddrWrite(){
    return uiAddrWrite;
}



//******************************************************************************//
//  Sets the address for the reading position. If the address is higher as the  //
//  max. memory address, then the writing address will be 0x00.                 //
//******************************************************************************//
void AT24C64D::setAddrRead(uint16_t Addr){    
    if(uiAddrRead > MEM_ADDR_MAX)   uiAddrRead = 0;
    else                            uiAddrRead = Addr;

}


//******************************************************************************//
// Increments the writing address. If the address is higher as the max. memory  //
// adress, it will be roll over.                                                //
//******************************************************************************//
void AT24C64D::incAddrRead(){
    if(uiAddrRead >= MEM_ADDR_MAX) uiAddrRead = 0;
    else                            uiAddrRead++;
}



//******************************************************************************//
// Decrements the writing address. If the address is smaller or equals to zero, //
// it will be roll over.                                                        //
//******************************************************************************//
void AT24C64D::decAddrRead(){
    if(uiAddrRead <= 0)             uiAddrRead = 4095;
    else                            uiAddrRead--;
}



//******************************************************************************//
//  Returns the current reading address.                                        //
//******************************************************************************//
uint16_t AT24C64D::getAddrRead(){
    return uiAddrRead;
}


//******************************************************************************//
//  After an interruption in protocol, power loss or system reset, the 2-wire   //
//  part can be protocol reset.                                                 //
//******************************************************************************//
void AT24C64D::reset(){
    i2c->start();
    i2c->write(0x00);
    i2c->start();
    i2c->stop();
    
    return;
}



/******************************************************************************/
// not implemented
/******************************************************************************/
bool  AT24C64D::erase(){
    return NACK;
}



//******************************************************************************//
//  Writes a data byte to the current write address (uiAddrWrite). If all       //
//  transmitions are successful, it will be returned a ACK. Otherwise a NACK.   //
//  The uiAddrWrite will be incremented, if the transmition was successfull.    //
//******************************************************************************//
bool AT24C64D::write(char * cData){
    return write(uiAddrWrite, cData);
}
    
    
//******************************************************************************//
//  Writes a data byte to the given address uiAddr. If all transmitions are     //
//  successful, it will be returned a ACK. Otherwise a NACK. The uiAddrWrite    //
//  will be set and incremented, if the transmition was successfull.            //      
//******************************************************************************//
bool AT24C64D::write(uint16_t uiAddr, char * cData){
    
    bAck        = NACK;
    uiTimeOut   = TIMEOUT_VAL; 
    
    
    while(not isReady());
    ACKpolling(AT24C64D_W);
    
    uiAddr      = uiAddr & ADDR_MASK;            
    cBuffer[0]  = (uiAddr >> 8) & 0xFF;
    cBuffer[1]  = uiAddr & 0xFF;
    cBuffer[2]  = (*cData);      
    
    //printf("Write on EEPROM address 0x%02x %02x the Byte 0x%02x\n", cBuffer[0], cBuffer[1], cBuffer[2]);

    bAck &= i2c->write(AT24C64D_W, cBuffer, 3);
    startTimer();
    
    
    uiAddrWrite = uiAddr;
    //incAddrWrite();
    
    return bAck;
}


//******************************************************************************//
//  Writes a data byte to address uiAddr. If all  transmitions are successful,  //
//  it will be returned a ACK. Otherwise a NACK. After every successful         //
//  transmition, the writeAddr will new set and at the end incremented.         //       
//******************************************************************************//
bool AT24C64D::write(uint16_t uiAddr, char * cData, uint16_t uiLength){
    return NACK;
}




//******************************************************************************//
//
//******************************************************************************//
bool AT24C64D::read(char *cData){ 
    return read(uiAddrRead, cData);
}


//******************************************************************************//
//
//******************************************************************************//
bool AT24C64D::read(uint16_t uiAddr, char *cData){ 
    
   // bAck = ACKpolling(AT24C64D_R);                                              // polling for ACK
    
    //if(bAck == ACK){

        uiAddrRead = uiAddr & ADDR_MASK;               
        cBuffer[0] = (uiAddrRead >> 8) & 0xFF;
        cBuffer[1] = uiAddrRead & 0xFF;
        
        i2c->start();
        i2c->write(AT24C64D_W);
        i2c->write(cBuffer[0]);
        i2c->write(cBuffer[1]);
        //i2c->read(AT24C64D_R, cData, 10);
        
        i2c->start();
        i2c->write(AT24C64D_R);
        *cData = i2c->read(false);
        i2c->stop();
    //}
    return bAck;
}



//******************************************************************************//
//  Reads data with length uiLength from Memory on address uiAddr. If all       //
//  transmitions are successful, it will be returned a ACK. Otherwise a NACK.   //
//  After every successful transmition, the readAddr will new set and at the    //
//  end incremented. When the memory address limit is reached, the data word    //
//  address will “roll over” and the sequential read will continue.             //
//******************************************************************************//
bool AT24C64D::read(uint16_t uiAddr, char *cData, uint16_t uiLength){ 
    
    if(uiLength == 0){
        printf("Read from EPPROM with a size of 0\n");
        return NACK;
    }
    
    //ACKpolling(AT24C64D_R);
    
    
    
    uiAddrRead = uiAddr & ADDR_MASK;    
            
    cBuffer[0] = (uiAddrRead >> 8) & 0xFF;
    cBuffer[1] = uiAddrRead & 0xFF;
    int iPos = 0;
    
    i2c->start();
    i2c->write(AT24C64D_W);
    i2c->write(cBuffer[0]);
    i2c->write(cBuffer[1]);
    i2c->start();
    i2c->write(AT24C64D_R);
    while(iPos < uiLength - 1){
        cData[iPos] = i2c->read(true);
        iPos++;
    }
    cData[iPos] = i2c->read(false);
    i2c->stop();
    
    return bAck;
}



/******************************************************************************/
//
/******************************************************************************/
bool AT24C64D::isReady(){
    
    if(timer->read_ms() > READY_TIME_MS){
        //printf("Time: %d\n", timer->read_ms());
        bReady = true;

        if(bTimerRun){
            timer->stop();
            bTimerRun = false;
        }
    }
    
    return bReady;
}


/******************************************************************************/
//
/******************************************************************************/
void AT24C64D::startTimer(){
    
    timer->start();
    timer->reset();

    bReady      = false;    
    bTimerRun   = true;
}



/******************************************************************************/
//
/******************************************************************************/
bool AT24C64D::ACKpolling(uint8_t uiAdr){
    
    bAck        = NACK;
    uiTimeOut   = TIMEOUT_VAL;
    
    while(bAck != ACK){
        i2c->start();
        bAck = (bool) i2c->write(uiAdr);                                        // return 0 -> NACK | 1 -> ACK | 2 -> TimeOut
        i2c->stop();
        
        uiTimeOut--;
        if(uiTimeOut == 0){
            printf("Read from EPPROM: timeout\n");
            return NACK;
        }       
    
        wait(100e-6);
    }
    
    return bAck;
}