Where does the Atmega328 datasheet state anything about the 32 byte buffer / maximum length of data per one transmission used in I2C?
Motivation:
I want to increase the write speed of an I2C EEPROM.
Quite a few web pages explain how to write several bytes to an I2C EEPROM in one transmission using "page-write" (eg http://www.hobbytronics.co.uk/eeprom-page-write). With this command one page (up to 32 or 64 bytes) can be written at once, but the Arduino buffer size limits the data length at 30 bytes (+2 address bytes) at once, though I could not find this info in the datasheet, hence question on top.
Because of this limitation the usual page-write examples breakdown the data in 16 byte chunks (followed with a mandatory 5ms delay).
Idea
Assuming f the I2C TX buffer is of the type "first in, first out", then the buffer is filled with 29 bytes of data and the 2 address bytes. After waiting 1ms (during which the transmission is already going on and thus creating space in the buffer), additional bytes are written into the buffer.
Test
In the linked example, a total of 280 bytes is written in 16 byte pieces.
The total transmission time was ~146 ms, one chunk of 16 bytes took 1.9ms (not counting the following 5ms delay). Note that this is the run time of the program code, not the actual time measured on signal wires.
My modified code took only 100 ms for the total write time.
PROBLEM:
Only most of the data is stored correctly. I notice quite a few errors when reading the data, not just around the 30-32 byte boundary. So the question is why?
Here is my modified code:
void writeEEPROMnew(int deviceaddress, unsigned int eeaddress, char* data) {
unsigned char i=0, counter=0;
unsigned int address;
unsigned int page_space;
unsigned int page=0;
unsigned int num_writes;
unsigned int data_len=0;
unsigned char first_write_size;
unsigned char last_write_size;
unsigned char write_size;
// Calculate length of data
do{ data_len++; } while(data[data_len]);
// Calculate space available in first page
page_space = int(((eeaddress/64) + 1)*64)-eeaddress;
first_write_size=page_space; //modified
if (first_write_size==0) first_write_size=32; //was 16 instead of 32
// calculate size of last write
if (data_len>first_write_size)
last_write_size = (data_len-first_write_size)%32; //was 16
// Calculate how many writes we need
if (data_len>first_write_size)
num_writes = ((data_len-first_write_size)/32)+2; // was 16
else
num_writes = 1;
i=0;
address=eeaddress;
for(page=0;page<num_writes;page++)
{
if(page==0) write_size=first_write_size;
else if(page==(num_writes-1)) write_size=last_write_size;
else write_size=32;//was 16
Wire.beginTransmission(deviceaddress);
Wire.write((int)((address) >> 8)); // MSB
Wire.write((int)((address) & 0xFF)); // LSB
counter=0;
do{
Wire.write((byte) data[i]);
i++;
counter++;
if (counter == 29) delay(1);
} while((data[i]) && (counter<write_size));
Wire.endTransmission();
address+=write_size; // Increment address for next write
delay(5); // needs 5ms for page write
}