Code

#define TABS        1
#define TAB         2
#define CAPSLOCK    4
#define LSHIFT      8
#define CODE        16
#define MARGIN      32
#define WORDERASER  64
#define CORRECT     128
#define RSHIFT      256
#define HALF        512
#define BS          1024

int r_pins[] = {8, 22, 24, 26, 28, 30, 32, 50};
int w_pins[] = {38, 40, 42, 44, 46, 48, 52};
int debounceThreshold = 135;         // Milliseconds to wait to ensure keys have settled and we process them

// 10   11   12   13   14   15   17
char* kdata[][8] = { // Keypress
  {"k", "l", ";", "'", "m", ",", "."},             // 1
  {"u", "i", "o", "P", "!", "!", "j"},             // 2
  {"7", "8", "9", "0", "-", "=", "!"},             // 3
  {"!", "1", "2", "3", "4", "5", "6"},             // 4
  {"!", "q", "w", "e", "r", "t", "y"},             // 5
  {"!", "a", "s", "d", "f", "g", "h"},             // 6
  {"!", "z", "x", "c", "v", "b", "n"},             // 7
  {"!", "/", "!", "!", " ", "!", "!"},             // 16
};
char* udata[][8] = { // 'Uppercase' map
  {"K", "L", ":", "\"", "M", "<", ">"},            // 1
  {"U", "I", "O", "P", "!", "!", "J"},             // 2
  {"&", "*", "(", ")", "_", "+", "!"},             // 3
  {"!", "!", "@", "#", "$", "%", "^"},             // 4
  {"!", "Q", "W", "E", "R", "T", "Y"},             // 5
  {"!", "A", "S", "D", "F", "G", "H"},             // 6
  {"!", "Z", "X", "C", "V", "B", "N"},             // 7
  {"!", "?", "!", "!", " ", "!", "!"},             // 16
};
char* sdata[][8] = { // Special keys
  {" ", " ", " ", " ", " ", " ", " "},             // 1
  {" ", " ", " ", " ", "H", "E", " "},             // 2
  {" ", " ", " ", " ", " ", " ", "D"},             // 3
  {"Z", " ", " ", " ", " ", " ", " "},             // 4
  {"T", " ", " ", " ", " ", " ", " "},             // 5
  {"C", " ", " ", " ", " ", " ", " "},             // 6
  {"L", " ", " ", " ", " ", " ", " "},             // 7
  {"S", " ", "O", "M", " ", "W", "R"},             // 16
};
unsigned int flags = 0;
char gotChar = ' ';
char uChar = ' ';
unsigned int debounceWait = 0;
int capsLock = 0;

void setup() {
  int i;
  Serial.begin(9600);
  delay(1500);

  Serial.println("Setting up pins");
  for (i = 0; i <=7; i++) {
    pinMode(r_pins[i], INPUT_PULLUP);
  }
  for (i = 0; i <=6; i++) {
    pinMode(w_pins[i], OUTPUT);
    digitalWrite(w_pins[i], HIGH);
  }
  
  // Configuration display
  Serial.print("Debounce threshold: ");  Serial.println(debounceThreshold);
  int sz = sizeof(flags);
  Serial.print("unsigned int size: "); Serial.println(sz);

  Serial.println("Ready...");
}


void loop() {
  int r;  int w;  int val;

  // Scan rows individually by bringing the column low and checking the rows for grounded pins
  for (w = 0;  w <= 6; w++) {
    digitalWrite(w_pins[w], LOW);
      for (r = 0; r <= 7; r++) {
        val = digitalRead(r_pins[r]);
        if (val == 0) {
          // This signal is grounded, so we have a keypress

          // Check to see if this is a Special Key
          if (*sdata[r][w] != ' ') {
            if (*sdata[r][w] == 'L') {
              flags |= LSHIFT;            // Left shift
            } else if (*sdata[r][w] == 'S') {
              flags |= RSHIFT;            // Right shift
            } else if (*sdata[r][w] == 'Z') {
              flags |= TABS;              // TabS
            } else if (*sdata[r][w] == 'T') {
              //flags |= TAB;               // Tab
              gotChar = '\t';
            } else if (*sdata[r][w] == 'C') {
              flags |= CAPSLOCK;          // CAPSLOCK
            } else if (*sdata[r][w] == 'O') {
              flags |= CODE;              // Code
            } else if (*sdata[r][w] == 'M') {
              flags |= MARGIN;            // Margin
            } else if (*sdata[r][w] == 'W') {
              flags |= WORDERASER;        // WordEraser
            } else if (*sdata[r][w] == 'R') {
              flags |= CORRECT;           // Correct
            } else if (*sdata[r][w] == 'H') {
              flags |= HALF;              // Half
            } else if (*sdata[r][w] == 'D') {
//              flags |= BS;                // Back space
               gotChar = '\b';
            } else if (*sdata[r][w] == 'E') {
              gotChar = '\n';             // Enter
            }
            if (debounceWait == 0) { debounceWait = millis(); }    // Set the debounce timer if it isn't already
        } else {
            gotChar = *kdata[r][w];
            uChar = *udata[r][w];
            if (debounceWait == 0) { debounceWait = millis(); }    // Set the debounce timer if it isn't already
          }
        }
      }
    digitalWrite(w_pins[w], HIGH);
    }

  // Finished scanning keyboard - if we've set the debounce timer, AND the debounce timer has passed
  if (debounceWait != 0 && (millis() - debounceWait) > debounceThreshold) {
    if (gotChar != '\0') {
      if (capsLock || ((flags & LSHIFT) == (LSHIFT)) || ((flags & RSHIFT) == (RSHIFT))) {
        gotChar = uChar;
      }
      Serial.print(gotChar);
    }


  if ((flags & CAPSLOCK) == CAPSLOCK) {  
    if (!capsLock) { capsLock = 1; } else { capsLock = 0; }
  }
    
  // Clear everything out for the next keypress
  gotChar = '\0';
  flags ^= flags;
  debounceWait = 0;
    
  }
}