After digging into I²C protocol some more I felt armed to hack the MultiSerial library to do multi-byte reads and writes. I added 2 user level functions – writeMulti() and readBuf(). I had to add 2 more internal functions – the ones that talk to the Wire lib. But as I tried to write the internal msWriteRegisterMulti() and msReadRegisterBuf(), while Wire did seem to support multi-byte operations, the bits I needed weren’t exposed as public.
OK – if I have to I’ll make a private Wire.h with more things exposed. But that wasn’t enough: the code used by Wire isn’t in wire.cpp – it’s in the underlying twi.cpp! I really didn’t want to make a private version of that, too!
Google and I could find little or nothing about heavy use of Wire (and twi) for making other libs like the one I needed. But I finally figured out how it actually works – and by working with the system, everything I needed was there. I put crude versions of all the routines in. No sanity checking, no error returns. Use it perfectly and it works. Else – no promises.
Wrapping my application level routines – writeMsg() and rxpoll() in millis() timers, I got some numbers. All are for sending/receiving a 27 byte message.
byte-at-a-time send: 330 ms multi-byte send: 4 ms
byte-at-a-time read: 800 ms multi-byte read: 7 ms
So how fast will it go end to end? I got up to about 1300 B/sec, but if I went faster the receive routine locked up. I suppose I should start handling some error conditions more gracefully 🙂
That’s plenty fast for the target applications, but not so much for bulk downloading of applications/problem sets/whatever via IR.
I sent a little update note to the original author of the lib and learned she was having performance problems with a VGA shield she was making and using I²C to talk to. So my multi-byte efforts may be the starting point for a performance boost for Strich Labs as well!
We are using the NXP I2C UART bridge as well. We need to read from a serial line that is at 115200 bps from Arduino. Currently we are getting buffer overruns and we are reading 1 byte at a time on the UART. We plan to increase the rate on Arduino TWI interface from 100Khz to 400Khz. It does sound like your Mulitbyte reads and writes would may be a benifit to our effort.
I do not think Strich Labs has added this feature to their MultiSerial library yet. Per the NXP documentation we should be able to read date from the UART at an acceptable rate at 400Khz.
But it sounds from your blog you have run into some issues using the i2C UART bridge. Do you think the multibyte read/write would help our issue ?
Yes, based on what I’ve seen with our devices, I expect the multi-byte read/write would help. The lib isn’t any place public yet (I’ll learn how to use github Real Soon Now, I promise!) but I’ll get you what we have.
Please note that the libs are far from robust. You must read from them frequently enough or (in our experience) the app can lock up in the driver, requiring a reset/power cycle to recover. Trying to fix that is on my list, and I even brought a couple of Educubes home from W88 to work on it, but it hasn’t happened yet. Maybe I can use your interest to inspire a little progress on it 🙂
In any event, you’re welcome to what we have, and I’ll get it to you soon.
I’ve sent the lib under separate cover.
Out of curiousity, do you mind sharing what you’re working on? Are you particularly married to older Arduinos? I think a Mega, with an ATMega2560 has 4 UARTs built in. Would that let you get the serial stream(s) in more easily?
In any event, good luck with your project!
The library as currently exists on Strich Labs’ Github did incorporate your changes for multi-byte write (the write() function is overloaded with two different sets of arguments for single or multi-byte writes) and removal of delays, both of which helped performance a lot. It doesn’t implement multi-byte reads yet, but I’ll look at getting that implemented in the next week or two as we port it to Arduino 1.0.