Code Equivalency between Arduino Functions and Register Instructions for TWI Bus

After presenting a data byte into a location of 24C512 EEPROM and then releasing the TWI Bus, we must wait for about 5 ms time period to allow the data byte actually getting written into the specified location of the EEPROM. Instead of stating 5 ms fixed time period, we may execute the following register instructions which will take as much time as is required to finish the ‘data writing process (1-byte)’ into the EEPROM. These are working codes and part of the attached program. Now, I am looking for equivalent codes for them in terms of Arduino Functions of the Wire.h Library. I have tried few options using (Wire.beginTansmission(), Wire.write(), and Wire.endTransmission()); but, they have not worked.

do
{
   TWCR = 0b10100100;    //START command to seize Bus (TWINT TWEA TWSTA TWSTO TWCC TWEA X TWIE)
   while((bitRead(TWCR, 7) != HIGH)
        ;                                //wait until action is completed
   TWDR = 0b10100100;     //EEPROM (device) address in write mode (SLA + W)
   while((bitRead(TWCR, 7) != HIGH)
        ;                 //wait until action is completed and status triggered by ACK of Slave 
}

while ((TWSR & 0b11111000), != 0x18);   //status is 0x18 as per data sheet

The above register oriented instructions are the direct translations of the following Algorithm (Fig-1) extracted from Microchip Data Sheet.

Figure-1: Algorithm describing the procedure of sensing ‘write done’ event

manyByteC.ino (2.03 KB)

I have tried few options using (Wire.beginTansmission, Wire.write(), and Wire.endTransmission()); but, they have not worked.

Here’s how Jack Christensen does it in his excellent library for using external eeproms https://github.com/JChristensen/extEEPROM

//Write bytes to external EEPROM.
//If the I/O would extend past the top of the EEPROM address space,
//a status of EEPROM_ADDR_ERR is returned. For I2C errors, the status
//from the Arduino Wire library is passed back through to the caller.
byte extEEPROM::write(unsigned long addr, byte *values, unsigned int nBytes)
{
    uint8_t ctrlByte;       //control byte (I2C device address & chip/block select bits)
    uint8_t txStatus = 0;   //transmit status
    uint16_t nWrite;        //number of bytes to write
    uint16_t nPage;         //number of bytes remaining on current page, starting at addr

    if (addr + nBytes > _totalCapacity) {   //will this write go past the top of the EEPROM?
        return EEPROM_ADDR_ERR;             //yes, tell the caller
    }

    while (nBytes > 0) {
        nPage = _pageSize - ( addr & (_pageSize - 1) );
        //find min(nBytes, nPage, BUFFER_LENGTH) -- BUFFER_LENGTH is defined in the Wire library.
        nWrite = nBytes < nPage ? nBytes : nPage;
        nWrite = BUFFER_LENGTH - _nAddrBytes < nWrite ? BUFFER_LENGTH - _nAddrBytes : nWrite;
        ctrlByte = _eepromAddr | (byte) (addr >> _csShift);
        Wire.beginTransmission(ctrlByte);
        if (_nAddrBytes == 2) Wire.write( (byte) (addr >> 8) );   //high addr byte
        Wire.write( (byte) addr );                                //low addr byte
        Wire.write(values, nWrite);
        txStatus = Wire.endTransmission();
        if (txStatus != 0) return txStatus;

        //wait up to 50ms for the write to complete
        for (uint8_t i=100; i; --i) {
            delayMicroseconds(500);                     //no point in waiting too fast
            Wire.beginTransmission(ctrlByte);
            if (_nAddrBytes == 2) Wire.write((byte)0);        //high addr byte
            Wire.write((byte)0);                              //low addr byte
            txStatus = Wire.endTransmission();
            if (txStatus == 0) break;
        }
        if (txStatus != 0) return txStatus;

        addr += nWrite;         //increment the EEPROM address
        values += nWrite;       //increment the input data pointer
        nBytes -= nWrite;       //decrement the number of bytes left to write
    }
    return txStatus;
}

He uses this for loop

 //wait up to 50ms for the write to complete
        for (uint8_t i=100; i; --i) {
            delayMicroseconds(500);                     //no point in waiting too fast
            Wire.beginTransmission(ctrlByte);
            if (_nAddrBytes == 2) Wire.write((byte)0);        //high addr byte
            Wire.write((byte)0);                              //low addr byte
            txStatus = Wire.endTransmission();
            if (txStatus == 0) break;
        }

@cattledog

Following your hints of Post#1, I have executed the following codes, instead of inserting 5 ms fixed time period or register dependent codes, to check the ‘EEPROM write End’ event. It works. My previous efforts did not work because of not knowing that Wire.endTransmission() function returns some Arduino-styled Status values.

Thanks a lot!

do
{
   Wire.beginTransmission(deviceAddress);  //EEPROM (device) address
   Wire.write (0x00);                      //dummy; it is to insert W-bit after 7-bit device address
   Wire.endTransmission();
}

while (Wire.endTransmission() != 0x00); //returns 0x00 if transmission is successful

manyByteC.ino (2.21 KB)