Jay's Projects

Voiding warranties since 1978, one product at a time

Video Peggy Miscellanea

October 24, 2008

Background

This page is a catch-all for updates/addons to my Video Peggy project. The basic project consists of hardware and firmware mods to the Peggy 2.0 kit to facilitate low-rez streaming video from an outside source (such as a PC). If you're not already familiar with this project, you should probably review the pages for the original hardware-mod version, as well as the improved "no-mod" version (all the cool videos are on those pages). Client code from this page will work on either version.

Quartz Composer plugin

All of the videos that I had previously posted demonstrated used Quartz Composer as a source. In order to make that work, I had to create a QC Patch that could take a bitmap and render it out as a stream of bytes to a serial port. I'm making the code for the QC patch available under a GPL license.

XCode
Plugin code in XCode.

Quartz Composer Serial-to-Peggy2 Plugin Source. Requires XCode 3.0 or higher on OS X 10.5 (Leopard).
This code should be considered experimental, and may have nasty bugs. Please read the README for more information on how to use the patch.

Processing Sample Code

Processing is an "open source programming language and environment for people who want to program images, animation, and interactions". Based on Java, it is cross platform. The libraries are high-level, easy to use, and fun to play around with. Looking for a cross-platform way to send data to a Peggy rather than the OS X-only QC solution, Processing was an obvious choice.

XCode
Still pictures of the bouncing circle just don't do it justice.

I didn't put the effort in to write a library for Processing, but what follows are instructions for modifying an existing sketch to send output to a Peggy running the "Video Peggy" firmware. This code is currently a bit inefficient, I'm open for suggestions on how to improve the performance..

First, add this code to the beginning of the sketch:

import processing.serial.*;

Serial peggyPort;
PImage peggyImage = new PImage(25,25);
byte [] peggyHeader = new byte[] 
    { (byte)0xde, (byte)0xad, (byte)0xbe,(byte)0xef,1,0 };
byte [] peggyFrame = new byte[13*25];

Add this line to the setup() method to open the serial port :


// be sure to use the correct serial port name below or the sketch will hang! 
peggyPort = new Serial(this, "/dev/tty.usbserial-XXXXXXX", 115200);

Add this method, which takes a PImage and renders it to the Peggy via the serial port:

// render a PImage to the Peggy by transmitting it serially.  
// If it is not already sized to 25x25, this method will 
// create a downsized version to send...
void renderToPeggy(PImage srcImg)
{
  int idx = 0;
  
  PImage destImg = peggyImage;
  if (srcImg.width != 25 || srcImg.height != 25)
    destImg.copy(srcImg,0,0,srcImg.width,srcImg.height,
                 0,0,destImg.width,destImg.height);
  else
    destImg = srcImg;
    
  // iterate over the image, pull out pixels and 
  // build an array to serialize to the peggy
  for (int y =0; y < 25; y++)
  {
    byte val = 0;
    for (int x=0; x < 25; x++)
    {
      color c = destImg.get(x,y);
      int br = ((int)brightness(c))>>4;
      if (x % 2 ==0)
        val = (byte)br;
      else
      {
        val = (byte) ((br<<4)|val);
        peggyFrame[idx++]= val;
      }
    }
    peggyFrame[idx++]= val;  // write that one last leftover half-byte
  }
  
  // send the header, followed by the frame
  peggyPort.write(peggyHeader);
  peggyPort.write(peggyFrame);
}

you can then add some code to your draw() method, calling renderToPeggy() with a PImage that you want it to display.

Suppose you want to simply mirror whats currently in the sketch window? Well, we first need to grab it somehow, and I couldn't find a direct way to do that, so I came up with this method, which (inefficiently) creates a PImage from the sketch window's pixels array:

// this method creates a PImage that is a copy 
// of the current processing display.
PImage grabDisplay()
{
  PImage img = createImage(width, height, ARGB);
  loadPixels();
  arraycopy(pixels, 0, img.pixels, 0, width * height);
  return img;
}

You can then add the following call to the end of the draw() method:

renderToPeggy(grabDisplay());

Clear as mud? An actual sketch that has been modified this way might clarify the matter. This is a modified version of the Bounce sketch (from the Processing example code): PeggyBounce.pde

Whats next?

TODO: Add more client code examples. C# maybe?


 
advertisement