I Hate I2C!
I thought the Z-Gun controller board was all operational until we connected it to dangle this week when we discovered a number of problems.
Two of them proved to be with the code in the AVR processor & a third is a due to the limitations of the AVR I2C implementation & a bug in the Raspberry Pi I2C interface.
The AT Tiny series of processors does not have a true I2C interface instead it uses AVR’s “Universal Serial Interface” (USI) this needs to be managed is software to fully implement the interface & the Library I chose does this with the use of interrupts. This was the cause of most of the issues.
The Z-gun would work fine at the I2C default rate of 100khz but Neil needed to run at the higher speed of 400kz for his Giro controller.
the time taken for the AVR to enter the “Start Condition” interrupt meant that the Pi could have already set the Data line resulting in the erroneous detection of a “Stop Condition” if the higgest bit of the address was set (& as I was using Address 0x60 this was the case) , removing this check resolved the error & tests indicate the board will now happily work up to 2Mhz! (except for Bug 3).
The AVR would could crash the I2C bus when data was being transmitted to other devices. this was a tricky one to pin down but was finally found to be due to one of the “Helpful” features of the USI, when the USI counter overflows (after reception of a full 8 clocks) it will trigger an interrupt & hold the clock low to prevent further transmission until the byte has been processed (it also does this for the ACK bit). When the AVR received an Addr. for another device it would turn off the data interrupt & wait for another Start condition, the original library did not disable the clock stretching at this point meaning that after a further 8 clocks it would pull the SCK line low but not enter the interrupt to process the data (because it was meant for another device) and clear the CLK. this was a simple fix, simply clearing the necessary bit in the control register when the received Address byte did not match the Address f the AVR.
Bug 3 did not come to light untill Bugs 1 & 2 were resolved
although writing to the AVR was problem free, reading data back any faster then 100khz failed. This turned out to be a combination of the AVR interrupt delays & the Raspberry Pi’s I2C implementation. for a more in depth explanation including traces from my BitScope see Raspberry Pi I2C Hardware Bug