Ok, here are some ways to do what I wanted.
For both methods below we want to use the 1mhz I2C clock and send data to the 4725 in the three byte mode (address + 2 data bytes) and not the slower 4 byte mode. IntervalTimer at whatever sample rate you want (*see note at end) .
The three byte mode uses [0] = address, [1] = 0000xxxx where xxxx = the upper 4 bits of the 12 bit data and the four zeros set the dac speed and power registers [2] = lower 8 bits of the 12bit data
The safe way: (IntervalTimer at 125 microseconds - 8k samples sent per second)
Push the address and two data bytes in.
call endTransmission() - 23% cpu time spent in ISR
slowest as it waits for each byte to be sent and all the error checking to be ok.
call endTransmission(false) - 15.5% cpu time spent in ISR
- faster - the code does not wait to see what happened to the last byte.
Either way of doing it means you will lose quite a bit of cpu time waiting for everything to transmit and be checked.
The shorter your IntervalTimer/higher the sample rate, the more CPU you waste waiting.
The fastest and dirty way (works for me):
endTransmissionFIFO() < 1% time spent in ISR at 125 microsecond interval
Code:
uint8_t TwoWire::endTransmissionFIFO(void)
{
/*
1of9's lossy two wire v0.1 - the goal of this function is to shove data into the fifo and return quickly
assumes only one master and slave and that we have control of the bus - no Arbitration checking
clears the fifo and shoves up to 4 bytes into it - minimal error checking - use at your own risk
seriously - this method just does not care about anything other than too much or no data available
*/
if (!txBufferLength) return 4; // no data to transmit
if (txBufferLength > 4) return 1; // data too large for FIFO
port->MCR = LPI2C_MCR_MEN | LPI2C_MCR_RTF; // clear the FIFO
port->MSR = LPI2C_MSR_PLTF | LPI2C_MSR_ALF | LPI2C_MSR_NDF | LPI2C_MSR_SDF | LPI2C_MSR_FEF; // clear flags
port->MTDR = LPI2C_MTDR_CMD_START | txBuffer[0];
if (txBufferLength > 1) port->MTDR = LPI2C_MTDR_CMD_TRANSMIT | txBuffer[1];
if (txBufferLength > 2) port->MTDR = LPI2C_MTDR_CMD_TRANSMIT | txBuffer[2];
if (txBufferLength > 3) port->MTDR = LPI2C_MTDR_CMD_TRANSMIT | txBuffer[3];
return 0;
}
endTransmissionFIFO at 32 microsecond interval - 3% cpu time spent in ISR
* Theortical maximum send rate is about 30k'ish samples per second (24 bits data + control bits + misc dead time) and I get a clean output at a 32 microsecond interval on the timer.
There is jitter in the output and this is far from being "HiFi" but it does what I wanted.