# How to make Arduino do High Speed I2C

I wired up two MCP4725 DAC's to my Arduino and wrote a little demo sketch to test functionality. The sketch draws a Lissajous curve on my oscilloscope. The output frequency is a bit disappointing (approx. 1.5kHz sample rate), but the datasheet to the DAC mentions High Speed I2C mode. Does Arduino (Mega1280) support High Speed I2C mode and if 'yes' how?

#include <Wire.h>
#include <math.h>

#define DAC0 ( 0xCC >> 1 )
#define DAC1 ( 0xCE >> 1 )

int sh[ 360 ] , sl[ 360 ];
int ch[ 360 ] , cl[ 360 ];

void setup() {
Wire.begin();
for ( int a = 0; a <= 360; a++ ) {
int s = sin( a * 3.141592 / 180 ) * 2047 + 2048;
int c = cos( a * 3.141592 / 180 ) * 2047 + 2048;
sh[ a ] = int( s / 256 );
sl[ a ] = s - sh[ a ] * 256;
ch[ a ] = int( c / 256 );
cl[ a ] = c - sh[ a ] * 256;
}
}

void loop() {
for ( int b = 0; b < 360; b++ ) {
for ( int a = 0; a < 360; a += 6 ) {
Wire.beginTransmission( DAC0 );
Wire.send( ch[ a ] );
Wire.send( cl[ a ] );
Wire.endTransmission();
Wire.beginTransmission( DAC1 );
Wire.send( sh[ ( a * 2 + b ) % 360 ] );
Wire.send( sl[ ( a * 2 + b ) % 360 ] );
Wire.endTransmission();
}
}
}

-
 A quick calculation (1.5[kS/s]×2[DAC's]×30[bits/frame]) gives 100kb/s, not even the 400kb/s I was expecting to use. – jippie Apr 7 '12 at 16:04

I would consider going one level below the C++ object "Wire" and use their C files found here:

https://github.com/arduino/Arduino/tree/master/libraries/Wire/utility

There is a constant of interest in twi.h:

#define TWI_FREQ 100000L

And the register is set in the file twi.c like so:

// initialize twi prescaler and bit rate
cbi(TWSR, TWPS0);
cbi(TWSR, TWPS1);
TWBR = ((F_CPU / TWI_FREQ) - 16) / 2;

/* twi bit rate formula from atmega128 manual pg 204
SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR))
note: TWBR should be 10 or higher for master mode
It is 72 for a 16mhz Wiring board with 100kHz TWI */


Going by that comment, and without having to go into the datasheet (although I suggest that you do if you want to understand what those lines mean), it appears that the Arduino Mega (16 MHz) defaults to 100 kHz I2C clock. Following the formula given, change the value of TWI_FREQ to achieve a desired I2C clock frequency.

However, after reading the datasheet of the Atmega, it appears to me that the fastest you can get [See edit]. Take a look at the section 24.5.2 Bit Rate Generator Unit to confirm this. If you define "High Speed" to be 3.4 MHz I2C, then the answer appears to be no, you can't achieve that with your current hardware, but you should be able to get something faster than the default 100 kHz if you really want to.

EDIT: It may be possible to achieve 1 MHz if I'm reading the datasheet correctly. Formula used from the datasheet: SCL = (F_CPU)/(16 + 2*TWBR*4^TWPS) The disclaimer below still stands :p

Disclaimer: I just took a quick glance at the docs to come up with the above, it's totally possible that I missed something. Please read the datasheet to confirm any of this and familiarize yourself with your microcontroller, since you are wanting to do something that the Arduino library does not offer.

-
ah ... the TWI_FREQ confirms my suspicion of 100kb/s bus speed. – jippie Apr 7 '12 at 16:06
Adding TWBR = 10; after Wire.begin(); makes the bus run at 444kHz (the minimum according to the formula in your comment). Lower values work too (1 would be 888kHz), but I'll have to study the datasheet to verify your 250kHz statement. – jippie Apr 7 '12 at 16:24
@jippie, Please note that it's not my comment but one that I found in the underlying Arduino code - which I do not know if it's correct. My 250 kHz estimate is based on the formula given in the datasheet, under section 24.5.2 Bit Rate Generator Unit. Can I ask how you're verifying the clock speed? With external tools physically or...? – Jon L Apr 7 '12 at 16:33
Also note that the HS I2C protocol is little bit different. It requires a special 'start' byte that informs all slaves to go to HS I2C mode. The Atmega1280 doesn't have support for this, so if you want anything close to HS I2C you would need to bit-bang it. And I guess that may not be as fast as desired. – Hans Apr 7 '12 at 16:36
@jippie, slight edit – Jon L Apr 7 '12 at 16:46