Hello Ytai,
Great product - just love it!
I am not sure if this is the right group to send this request, if not please guide. I am hoping to make a positive contribution to this community.
I have used IOIO in past and have started using it for a pretty big project using some intricate hardware. I ran into problems for effectively using I2C devices and most of these were attributed to the fact that ioio.lib.api.TwiMaster.Result has a waitReady that blocks forever. This is problematic esp. when the I2C slave's behavior is not always completely determistic - as is the case with many complex hardwares. The thread blocks forever and recovery logic becomes more complex than original operation esp. when monitoring multiple such devices. For now I had to resort to some pretty ugly work-arounds. However, a waitReady in Result that times out - would make an application developer's task a lot easier. So I have the following suggestion, which I would appreciate if you can please consider to make something similar to this available in your next API release.
In ioio.lib.impl.ResourceLifeCycle, add the following method:
protected synchronized void safeWait(long millis) throws ConnectionLostException, InterruptedException {
if (state_ == State.CLOSED) {
throw new InterruptedException("Resource closed");
} else if (state_ == State.DISCONNECTED) {
throw new ConnectionLostException();
}
wait(millis);
}
In ioio.lib.api.TwiMaster.Result interface, add the following method:
public boolean waitReady(long millis) throws ConnectionLostException,
InterruptedException;
In ioio.lib.impl.TwiMasterImpl.TwiResult class, add the following method:
@Override
public synchronized boolean waitReady(long millis) throws ConnectionLostException,
InterruptedException {
checkState();
while (!ready_) {
safeWait(millis);
}
return success_;
}
Another issue for working with I2C devices, I was not able to come up with a reliable solution to "ping" a I2C slave with IOIO master to determine if slave is indeed present. For example, connecting my I2C device to a bus-pirate, master can write an address of the slave on the bus and obtain an ACK and this would be an indication that a slave is indeed present at that address. My logic analyzer shows the same with this bus-pirate setup. However, I did not have any such luck making it work with IOIO's TwiMaster.writeRead. I tried writing a 0-byte buffer (with read null buffer) and reading 0-byte buffer (with write null buffer) but seems I dont get any results - calls simply block. I would appreciate any help in this regards.
It would also help to obtain information on what was NACKed when writing+reading using TwiMaster.writeRead or TwiMaster.writeReadAsync returns false as currently, we have to split write and read into two separate invocations to know what failed esp. when error recovery depends on what failed.
I was able to handle most trivial apps fairly easily with the current APIs and I like the synchronous API in its elegance and simplicity. I recognize this is a subjective viewpoint - however, when time-critical processing, reliability and performance are critical, it becomes harder to overcome the absence of asynchronous event handling paradigm in API esp for devices such as I2C, UART. User ends up dedicating a thread per item to operate and for complex apps, thread synchronization across many threads is typically harder, error-prone and sometime lags quite a bit - when recovery depends on state of device(s) across many such threads. At IOIOProtocol level, we are getting the notifications from the board (asynchronous processing). I wonder if it is worthwhile to explore allowing users to use an asynchronous event handling paradigm - where user can register listeners for handling ingress traffic notifications rather than blocking for it in individual threads. Problem of a potential event-handler hogging the IOIOProtocol handling thread can be mitigated by user handling events using a thread-pool/queue. Please share your thoughts.
With regards,
-VB