sparkfun 4x4 keypad matrix

I have just done this using a Parallax 4x4 Keypad and the 74C922. It's a little tricky because you need to pool for changes on data available from LOW to HIGH, and then stop pooling until DA is back to LOW, otherwise it will send the key's value until you release it. There is also some issues with timing. Below is what I came up with (it also includes a little password example... just for fun). Improvements could be made, such as using a "soft delay" with millis() instead of using delay() (if you make it work, can you post an update?).

/* Parallax 4x4 Keypad using 74C922 16 Keys Encoder
 * ---------------
 *
 * Comments
 *
 * (cleft) 2005 by Matthieu Lalonde
 * <http://smurfturf.net/>
 * <mailto:mlalonde(at)smurfturf(dot)net>
 *
 */
#define BAUD_RATE 9600
#define statusLED 12

// Inputs from the 74C922 16 Keys Encoder
#define inputKey1 8
#define inputKey2 9
#define inputKey3 10
#define inputKey4 11

// The key encoder will provide HIGH on this pin when new data is available
#define dataAvailable 7

// Needed to manage inputs in a proper fashion (one entry per push)
int dataAvail      = LOW;
int lastDataAvail  = LOW;
byte keyValue      = 0;

// We need to slow down things a little, otherwise the 74C922 misbehaves
int interval       = 15;

char passwdValue[5] = {
  15, 3, 13, 1};
char passwdEntry[5];
int  entryNbr   = 0;
int  badTries   = 0;

void setup(void) {
  // initialize inputs/outputs
  pinMode(dataAvailable, INPUT);

  pinMode(inputKey1, INPUT);
  pinMode(inputKey2, INPUT);
  pinMode(inputKey3, INPUT);
  pinMode(inputKey4, INPUT);

  // start serial
  Serial.begin(BAUD_RATE);

  reportAVRState(3,1);
}

void loop(void) {
  dataAvail = digitalRead(dataAvailable);

  // Do we have a change in the state of dataAvailable or was the key just never released?
  if (dataAvail == HIGH && lastDataAvail == LOW) {
    lastDataAvail = dataAvail;
    delay(interval);

    // We do our business here
    keyValue = 0;
    keyValue = (digitalRead(inputKey1) << 3) + (digitalRead(inputKey2) << 2) + (digitalRead(inputKey3) << 1) + digitalRead(inputKey4);

    passwdEntry[entryNbr] = keyValue;

    Serial.print(keyValue, HEX);
    //Serial.println();
    entryNbr++;
    if (entryNbr == 4) {
      Serial.println();
      if (!strCompare(passwdValue, passwdEntry)) {
        Serial.print("We have a winner after ");
        Serial.print(++badTries);
        Serial.println(" times!");
        entryNbr = 0;
        badTries = 0;
      } 
      else {
        badTries++;
        Serial.print("We have a loser that tried ");
        Serial.print(badTries);
        Serial.println(" times!");
        entryNbr = 0;
      }
    }
  }
  // We need to reset the state of dataAvailable
  if (dataAvail == LOW && lastDataAvail == HIGH) {
    lastDataAvail = dataAvail;
    delay(interval);
  }
}

int strCompare(char *a, char *b) {
  while (a[0] && b[0]) {
    if (a[0] != b[0]) return 1;
    *a++;
    *b++;
  }

  if (a[0] != 0 || b[0] != 0) return 1;

  return 0; //they are the SAME
}

// Reports the state of the controller via pin 13's led and serial
void reportAVRState(int howManyTimes, int leaveOn) {
  int i;

  pinMode(statusLED, OUTPUT);

  for (i=0; i< howManyTimes; i++) {
    digitalWrite(statusLED, HIGH);
    delay(200);
    digitalWrite(statusLED, LOW);
    delay(200);  
  }

  if (leaveOn) { 
    digitalWrite(statusLED, HIGH); 
  }

  Serial.println("AVR Initialized");
}

Here is a picture of the circuit (using SparkFun's protoshield):

You can see a video example here.