 bool symbolShiftPressed = false;
 bool capsShiftPressed = false;
 
-// 
 bool enterPressed = false;
 bool deletePressed = false;
 bool leftPressed = false;

//  ZXKBFirmware v.05
//  Copyright 2016 Mike Daley

#include <Keyboard.h>

const int dataLines = 5;
const int addressLines = 8;
const int dataPin[dataLines] = {A0, A1, A2, A3, 15};          // The Pro-Micro does not have an A4 pin so using 15
const int address[addressLines] = {2, 3, 4, 5, 6, 7, 8, 9};
const int keyboardModeSpeakerPin = 10;                            // When LED is on keyboard is in special mode
const int keyboardModeButtonPin = 14;                         

// Tracking when special keys that need us to send specific USB keyboard values have been pressed means that

      // Get the value of the current data line...
      int pressed = digitalRead(dataPin[dataLine]);

      // ...and if it's LOW then a key has been pressed
      if (pressed == LOW) {

        // Deal with special keys by setting flags so we know what has been pressed
        if (addrLine == 7 && dataLine == 1 && !symbolShiftPressed) { // Symbol Shift
          symbolShiftPressed = true;
        } else if (addrLine == 5 && dataLine == 0 && !capsShiftPressed) { // Caps Shift
          capsShiftPressed = true;
        }

        int outKey = 0;

        // Manage what is sent from the keyboard based on the keyboard mode
        switch (keyboardMode) {
          
          case MODE_SPECTRUM:
            outKey = spectrumKeyMap[addrLine][dataLine];            
            break;
            
          case MODE_FUSE:
            outKey = fuseKeyMap[addrLine][dataLine];            
            break;
            
          case MODE_PC:
            // In PC mode we use the shift key being pressed to read keys from a different matrix making it
            // easier to assign different keys to Spectrum keyboard keys e.g. BREAK = BACKSPACE
            if (capsShiftPressed) {
              // Pressing a dedicated arrow key on the Spectrum+ keyboard actually regiters a CAPS SHIFT and then the
              // appropriate number for the arrow e.g. 5, 6, 7, 8. In PC mode this CAPS SHIFT means than as the cursor
              // moves it highlights as well. To stop this happening we release the CAPS SHIFT before sending the arrow
              // key. You now can't highlight with arrow keys but correct movement seemed more important :O)
              if ((addrLine == 3 && dataLine == 2) || (addrLine == 3 and dataLine == 3) || 
                 (addrLine == 3 && dataLine == 4) || (addrLine == 0 && dataLine == 4)) {
                  Keyboard.release(KEY_LEFT_SHIFT);
                 }
              outKey = pcKeyMapShifted[addrLine][dataLine];            
            } else {
              outKey = pcKeyMapNormal[addrLine][dataLine];            
            }
            break;
            
          default:
            if (debug) Serial.print("ERROR: Unknown keyboard mode");
        }

         // We know what has been pressed and taken the key stroke to be send from the appropriate
         // matrix array, so now send it and marked it as pressed in the keyPressed matrix array
        if (!keyPressed[addrLine][dataLine]) {
          if (debug) printDebug(addrLine, dataLine);
          Keyboard.press(outKey);
          keyPressed[addrLine][dataLine] = true;
        }

      // No key has been pressed so manage releasing any keys that were pressed
      } else {

        int outKey = 0;

        // Deal with special keys that may have been pressed previously set
        if (addrLine == 7 && dataLine == 1 && symbolShiftPressed) {      
          symbolShiftPressed = false;
        } else if (addrLine == 5 && dataLine == 0 && capsShiftPressed) {
          capsShiftPressed = false;
        } 
          
        // Based on the keyboard mode deal with releasing previously pressed keys
        switch (keyboardMode) {

          case MODE_SPECTRUM:
            outKey = spectrumKeyMap[addrLine][dataLine];            
            break;

          case MODE_FUSE:
            outKey = fuseKeyMap[addrLine][dataLine];            
            break;

          case MODE_PC:
            if (capsShiftPressed) { 
              outKey = pcKeyMapShifted[addrLine][dataLine];            
            } else {
              outKey = pcKeyMapNormal[addrLine][dataLine];            
            }
            break;

          default:
            if (debug) Serial.println("ERROR: Unknown keyboard mode");
        }

        // Check to see if the current matrix poition has a key press registered. If so then release
        // that key and mark it as released
        if (keyPressed[addrLine][dataLine]) {
          Keyboard.release(outKey);
          keyPressed[addrLine][dataLine] = false;
        } 
        
      }
    }

    // Set the address line back to HIGH
    digitalWrite(address[addrLine], HIGH);
  }

}

void beep(int pin, int duration, int frequency) {
  for (int x = 0; x < duration; x++) {
    digitalWrite(pin, HIGH);
    delayMicroseconds(frequency);
    digitalWrite(pin, LOW);
    delayMicroseconds(frequency);
  }
}

void printDebug(int addrLine, int dataLine) {
  int outKey = spectrumKeyMap[addrLine][dataLine];            
  Serial.print ("Addr Line: "); Serial.print(addrLine);
  Serial.print(" - ");
  Serial.print("Data Line: "); Serial.print(dataLine);
