Jay's Projects

Voiding warranties since 1978, one product at a time

Video Peggy using TWI (I²C) : The no-mods version

October 7, 2008


If you haven't seen my first Video Peggy page, you may want to skim that content first. In it, I describe a hardware modification to a Peggy 2.0 board as well as AVR code that can support a low-rez video stream. The modification was done to re-route some of the AVR pins so that the board could accept serial communication from a Mac or PC. Serial communication was the simplest way for me to test pumping a video stream to the board, and my original focus was proving the viability of the technique. However, serial communication is not the only way to do it, and I've since implemented a different way that does not require all the messy hardware modifications. All that is needed are the Peggy, an Arduino, and three wires to connect the two.

"Stock" Peggy 2.0 with Arduino. The protoboard under the AVR was created to make
it easy to swap with the serial version; it is a straight passthru and is NOT required.

We can rebuild it, we have the technology...

Once I had proven low-rez video workable with serial communication, I started looking at those mostly unused SDA/SCL pins on the stock Peggy board. On the Peggy PCB, SCL is unconnected, and SDA is used for the (optional) B5 button, but its a normally open, pull-to-ground button with a 5k or so pullup. So this means those pins can be used for I²C (aka I2C, 2-Wire or TWI) communication without otherwise modifying the board. We can then use some form of Serial-to-I2C translator to connect the Peggy to a PC/Mac, and an Arduino is perfect for this task.

So the basic setup would look something like this:

PC pushes data serially to the Arduino, which in turn pushes the same data to the Peggy via TWI/I2C.

Software Theory of Operation (Peggy)

The new Peggy firmware for TWI/I2C functions in a similar manner to the serial version. A timer interrupt refreshes the display by sequencing through the rows and sending SPI output to the chips that drive the LEDs. Meanwhile, the main program loop services the TWI registers in a "polled" manner as a TWI slave, receiving TWI data and stuffing it into a frame buffer.

The TWI code contains minimal error handling. It mainly just attempts to continue receiving regardless of any detected bus error conditions. There is no error correction, nor is it really necessary for processing video; it's better to keep moving and cover up any errors on the next frame than to have a complicated procedure for detecting and retransmitting errors. In practice, the protocol is very robust and errors are extremely rare anyway.

In addition to replacing the input code, I worked on optimizing the display interrupt, and managed to cut down the amount of CPU time required to refresh the display considerably. At the default refresh rate of 70 frames per second, the display interrupt now only takes roughly 1/3rd of the CPU time, which is almost half as much as it was before. On the input side, 30 frames per second are easily handled, and the code is capable of processing data at almost twice that rate. The code is also a bit smaller; the compiled firmware weighs in at about 1024 bytes.

Software Theory of Operation (Arduino)

The Arduino code works as a straightforward converter of serial data coming from the PC to TWI data going to the Peggy. Newer versions of the Arduino IDE (11 and up) come with a TWI library called "Wire". This made writing the conversion code almost trivial. It's simple enough that I'll post the main loop here:

void loop()
  int count = Serial.available();
  if (count > 0)
    // don't send more than 16 bytes at a time
    if (count > 16) count = 16;
    while (count-- > 0 )
      uint8_t c = Serial.read(); 

The code attempts to batch as many bytes as it can (up to 16), which is more efficient than writing one byte per transmission.

Some custom low-level code was used to the setup() method to work around some limitations in the Arduino library. Because of this, the Arduino sketch requires an Arduino Diecimila (Atmega168), although it can be made to work on a Atmega8 or '88 based boards with some minor modifications. The low level code reconfigures the clocks set for the Serial and the TWI libraries. The serial UART clock is changed so that it will be more reliable at 115k baud than the configuration that the Arduino library provides. Also, I override and increase the speed of the TWI clock, which is unfortunately hard coded to 100khz in the Wire library.

Quartz Composer -> Serial -> Arduino -> TWI ->Peggy 2.0.

Hardware interfacing instructions

IMPORTANT: You should install the firmware for both the Peggy and the Arduino before connecting the two devices. The two pins of each device will be wired directly together, and if one of these is set as an output on either of the devices, you'll have a short circuit, and you'll damage one or both of the AVRs. It might be prudent to use some inline 220 ohm resistors between the two, but I personally haven't tried this.

The hardware hookup is simple. The Arduino analog 4 and 5 pins are wired to the SDA and SCL pins on the Peggy (i.e. SDA to SDA and SCL to SCL). A third wire is required to connect the ground between the two boards. Pullups enabled in the Peggy firmware and the Arduino code, so you shouldn't need any pullup resistors. The Arduino is connected to the PC/Mac via USB.


This code should be considered experimental! Use at your own risk! Wear eye protection! Don't cross the streams! (It would be bad).

Video-Peggy-Twi AVR source code (2008-10-28). Also includes a Arduino sketch (.pde file) that acts as a serial to TWI translator, and a sample Python script that sends an animated test pattern from a PC. Now with makefile support for installing firmware on the Peggy using FTDI cable as well as ISP.

The QC plugin and other client code is now on this page.