I have an I2C slave using the USI of an ATTiny84. I have code loosely based on AVR312.
However, this only lets me poll "is there any data" from the application code -- it won't let me detect that the master has authoritatively sent a full packet of data.
On the Atmegas, with a built-in TWI engine, there exists a state that lets me do that. In the interrupt handler, I can schedule a task in my micro-task-system to actually pick up the complete packet and do something with it.
On the Tiny, I can send ack or nak based on whether I have buffer space left -- but there is no interrupt for the bus going into the STOP state. There is a bit I can check in USISR, but I can't get an interrupt when this changes.
The best I can think of is to schedule some timeout within the "I received a byte" function, and if no more bytes come within that timeout, decide that the packet is done, and hand the data off to the application code. This has three draw-backs:
1) It adds latency (not so bad)
2) It is not necessarily correct (worse)
3) It loses data if a new packet is started (stop+start condition) in the polling interval
Are there any better ideas? FWIW, I'm running the ATTiny at 8 Mhz, and it's being written to by a ATMega328p running at 16 MHz, running the bus at 400 kHz, although that really shouldn't matter for this question.
Perhaps staying in the interrupt routine after shifting out the ACK bit, but clearing the interrupt flag and clock counter, and poll SCL and SDA until one of them change, and detect whether that's STOP or not?
This would potentially still cause a latency increase for my main program because of the polling, but it might bet better than nothing.
Also, the master could drive the slave into watchdog timeout (currently 2 seconds) this way by simply keeping the lines idle after shifting out the ACK bit...