In the world of hardware hacking, you sometimes spend a ridiculous amount of time debugging a problem, only to find a simple solution that was right in front of you the whole time. [Zack Freedman] got a good dose of this while building the Optigon V2, a modified Epson Moverio wearable display he uses as a teleprompter in all his videos. He prefers having the teleprompter over his left eye only, but the newer version of the Moverio would shut off both sides if one is disconnected, so [Zack] needed a workaround.
Looking for some help from above, [Zack] requested developer documentation for the display module from Epson, but got declined because he wasn’t a manufacturer or product developer. Luckily, a spec sheet available for downloaded from the Epson website did contain a lot of the information he needed. An STM32 monitored the temperature of each display module over a pair of independent I2C interfaces, and would shut down everything if it couldn’t connect to either. This led [Zack] to attempt to spoof the I2C signals with an ATmega328, but it couldn’t keep up with the 400 kHz I2C bus.
However, looking at the logs from his logic analyzer, [Zack] found that the STM32 never talked to both display modules simultaneously, even though it is capable of doing so. Both displays use the same I2C address, so [Zack] could simply connect the two I2C buses to each other with a simple interface board, effectively making the left display “spoof” the signals from the right display.
Wearable displays need some fancy optics to be practical, you can’t just stick an OLED to your face. Two other interesting projects from [Zack] are his modular mechanical keyboard and the Gridfinity 3D printed storage system.
The ATmega328 not keeping up with a 400KHz I2C sounds odd, you need some really crappy code if you cannot keep that up… as that’s only 40KByte/s, giving you a few 100 cycles to handle each byte even at the internal 8Mhz clock.
I’ve ran into this before. Even at 8MHz it couldn’t keep up with a host that demanded no clock stretching. There’s only one vector for the TWI module, but with a bunch of status codes, and it has to do a ton of state machine code before replying.
From what he says in the video, the 328 hardware tries to enforce clock stretching that the Moverio doesn’t take into account because it was never intended to interface with other chips.
From a glimpse at the screenshots at 12:34 I guess that it is due to the use of Arduino-Libraries.
Oh, SPOILER ALERT for the video, BTW.
“enforcing clock stretching” refers to “keeping the SCL line low until the IRQ has been handled”. So the IRQ happens when the atmel has started pulling SCL low. The IRQ handler then has to check if the status is the expected 0xA8 (“Own SLA+R has been received; ACK has been returned”) and if that is the case has to determine the response byte and write it to TWDRx. To avoid clock stretching when running at 8MHz this has to happen within 8MHz/400kHz/2 = 100 cycles.
This should be fairly doable – unless you are using an infrastructure that has to look up and call previously registered callback functions that provide the data you actually want to return.