AMIGA 500/1000/2000 Keyboard Interface

Hi,

this turns your Arduino Leonardo into an AMIGA 500/1000/2000 Keyboard Interface which means that you can use your Amiga Keyboard as an HID Keyboard on your PC/Mac/PS3/Raspberry Pi or whatever. (like keyrah)
All you need is the Amiga Keyboard and the Arduino without any shield or additional hardware. It does not work with Amiga 600/1200 Keyboards since they have no serial interface.
It's also possible to hook up 2 digital joysticks (e.g. competition pro) with db9 connector.
see Arduino Forum

Based on Thomas Radtkes project Raspberry 500 / Amiga Pi ? - Raspberry Pi Forums I rewrote the code to make it faster and smaller. I also changed the behavier a little bit to match my own preferences.

The Keyboard must be connected to digital inputs 8,9,10 , GND and 5V. The Power LED can be directly connected to 5V
This is the pin assignment:

Keyboard   Leonardo
Connector  IO           

1   KBCLK   8
2   KBDATA  9
3   KBRST   10
4   5v      5v
5   NC
6   GND     GND
7   LED1    5V
8   LED2    -

This is the sketch for German QWERTZ Layout:
See Page 2 for QWERTY Layout (thanks Steve_Reaver)

#define BITMASK_A500CLK 0b00010000    // IO 8
#define BITMASK_A500SP  0b00100000    // IO 9
#define BITMASK_A500RES 0b01000000    // IO 10
#define BITMASK_JOY1    0b10011111    // IO 0..4,6
#define BITMASK_JOY2    0b11110011    // IO A0..A5    
#define SYNCH_HI        0
#define SYNCH_LO        1
#define HANDSHAKE       2
#define READ            3
#define WAIT_LO         4 
#define WAIT_RES        5

KeyReport _keyReport;
uint32_t counter = 0;
uint8_t Joy, MemoJoy1, MemoJoy2, state, bitn, key, fn,keydown, ktab[0x68]={
  // Tilde, 1-9, 0, sz, Accent, backslash, Num 0 (00 - 0F)
  0x35, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x2D, 0x2E, 0x31,    0, 0x62,
  // Q bis +, -, Num 1, Num 2, Num3 (10 - 1F)
  0x14, 0x1A, 0x08, 0x15, 0x17, 0x1C, 0x18, 0x0C, 0x12, 0x13, 0x2F, 0x30, 0   , 0x59, 0x5A, 0x5B,
  // A-#, -, Num 4, Num 5, Num 6 (20 - 2F)
  0x04, 0x16, 0x07, 0x09, 0x0A, 0x0B, 0x0D, 0x0E, 0x0F, 0x33, 0x34, 0x32, 0,    0x5C, 0x5D, 0x5E,
  // <>,Y- -, -, Num . , Num 7, Num 8, Num 9 (30 - 3F)
  0x64, 0x1D, 0x1B, 0x06, 0x19, 0x05, 0x11, 0x10, 0x36, 0x37, 0x38,    0, 0x63, 0x5F, 0x60, 0x61,
  // Space, BS, Tab, Enter, Return, ESC, Del, -, -, -, Num -, -, up, down, right, left (40 - 4F)
  0x2C, 0x2A, 0x2B, 0x58, 0x28, 0x29, 0x4C,    0,    0,    0, 0x56,    0, 0x52, 0x51, 0x4F, 0x50,
  // F1-F10, -, -, Num /, Num *, Num +, - (50 - 5F)
  0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43,    0,    0, 0x54, 0x55, 0x57,    0,
  // modifiers: Shift left, Shift right, -, Crtl left, Alt left, Alt right, Win (amiga) left, Ctrl (amiga)right
  0x02, 0x20, 0x00, 0x01, 0x04, 0x40, 0x08, 0x10 
};

void setup() {
  // Joystick 1 (Port D)
  DDRD = ~BITMASK_JOY1; // direction INPUT
  PORTD = BITMASK_JOY1; // activate PULLUP
  
  // Joystick 2 (Port F)
  DDRF = ~BITMASK_JOY2; // direction INPUT
  PORTF = BITMASK_JOY2; // activate PULLUP

  // Keyboard (Port B)
  DDRB = ~(BITMASK_A500CLK | BITMASK_A500SP | BITMASK_A500RES);  // direction INPUT
}


void loop() {
  // Joystick 1
  Joy = ~PIND & BITMASK_JOY1;
  if (Joy != MemoJoy1) {
    HID_SendReport(3, &Joy, 1);
    MemoJoy1 = Joy;
  }  

 // Joystick 2
  Joy = ~PINF & BITMASK_JOY2;
  if (Joy != MemoJoy2) {
    HID_SendReport(4, &Joy, 1);
    MemoJoy2 = Joy;
  }  
  
  // Keyboard
    if (((PINB & BITMASK_A500RES)==0) && state!=WAIT_RES) {   // Reset
    interrupts();
    keystroke(0x4C,05);        // CTRL+ALT+DEL
    fn=0;
    state=WAIT_RES;
  }
  
  else if (state==WAIT_RES) {   // Waiting for reset end
    if ((PINB & BITMASK_A500RES)!=0) state=SYNCH_HI;
  }
  
  else if (state==SYNCH_HI) {   // Sync-Pulse HI
    if ((PINB & BITMASK_A500CLK)==0) state=SYNCH_LO;
  }

  else if (state==SYNCH_LO) {   // Sync-Pulse LOW
    if ((PINB & BITMASK_A500CLK)!=0) state=HANDSHAKE;
  }
 
  else if (state==HANDSHAKE) {  // Handshake
    if (counter==0) {
      DDRB |= BITMASK_A500SP;   // set IO direction to OUTPUT
      PORTB &= ~BITMASK_A500SP; // set OUTPUT to LOW
      counter=millis();
    }
    else if (millis()-counter>10) {
      counter=0;
      DDRB &= ~BITMASK_A500SP;   // set IO direction to INPUT
      state=WAIT_LO;
      key=0;
      bitn=7;
    }
  }
  
  else if (state==READ) {        // read key message (8 bits)
    if ((PINB & BITMASK_A500CLK)!=0) {  
      if (bitn--){
        key+=((PINB & BITMASK_A500SP)==0)<<(bitn); // key code (add bits 0...6)
        state=WAIT_LO;
      }
      else {  // read last bit (key down)    
        keydown=((PINB & BITMASK_A500SP)!=0); // true if key down
        interrupts();
        state=HANDSHAKE;
        if (key==0x5F)  fn=keydown;  // "Help" key: special function on/off
        else if (key==0x62) keystroke(0x39,0x00);  // CapsLock
        else {
          if (keydown){
            // keydown message received
            if (fn) {
              // special function with "Help" key 
              if (key==0x50) keystroke(0x44,0);  // F11
              else if (key==0x51) keystroke(0x45,0);  // F12
              else if (key==0x5A) keystroke(0x53,0);  // NumLock
              else if (key==0x5B) keystroke(0x47,0);  // ScrollLock
              else if (key==0x5D) keystroke(0x46,0);  // PrtSc
              else if (key==0x02) keystroke(0x14,0x40);  // @
              else if (key==0x04) keystroke(0x35,0x02);  // °
            }
            else {
              if ((key==0x2B) && (_keyReport.modifiers & 0x22)) keystroke(0x35,0x00);  // ^ (with shift)
              else if (key==0x00) if (_keyReport.modifiers & 0x22) keystroke(0x30,0x40); else keystroke(0x35,0x20); // ~,`
              else if (key==0x0D) if (_keyReport.modifiers & 0x22) keystroke(0x64,0x40); else keystroke(0x2D,0x40); // |,BS
              else if (key==0x5A) if (_keyReport.modifiers & 0x22) keystroke(0x24,0x40); else keystroke(0x25,0x40); // {,[
              else if (key==0x5B) if (_keyReport.modifiers & 0x22) keystroke(0x27,0x40); else keystroke(0x26,0x40); // },]
              else if (key < 0x68) keypress(key);  // Code table
            }
          }
          else {
            // keyrelease message received
            if (key < 0x68) keyrelease(key);  // Code table
          }
        }
      }
    }
  }
  
  else if (state==WAIT_LO) {   // waiting for the next bit
    if ((PINB & BITMASK_A500CLK)==0) {
      noInterrupts();
      state=READ;
    }
  }
}
    

void keypress(uint8_t k) {
  
  if (k > 0x5f) _keyReport.modifiers |= ktab[key];  // modifier
  else {  
    for (uint8_t i=0; i<6; i++) {
      if (_keyReport.keys[i] == 0) {
         _keyReport.keys[i] = ktab[key];
         break;
      }
    }
  }
  HID_SendReport(2,&_keyReport,8);
}


void keyrelease(uint8_t k) {

  if (k > 0x5f) _keyReport.modifiers &= ~ktab[key];  // modifier
  else {  
    for (uint8_t i=0; i<6; i++) {
      if (_keyReport.keys[i] == ktab[key]) _keyReport.keys[i] = 0;
    }
  }
  HID_SendReport(2,&_keyReport,8);
}


void keystroke(uint8_t k, uint8_t m) {
  
  unsigned short memomodifiers = _keyReport.modifiers; // save last modifier state
    for (uint8_t i=0; i<6; i++) {
      if (_keyReport.keys[i] == 0) {
         _keyReport.keys[i] = k;
         _keyReport.modifiers = m;
         HID_SendReport(2,&_keyReport,8);
         _keyReport.keys[i] = 0;
         _keyReport.modifiers = memomodifiers; // recover modifier state
         HID_SendReport(2,&_keyReport,8);
         break;
      }
    }
}

Since I never owned a real Amiga I prefer the IBM layout for the modifier keys CTRL,ALT, etc.
So If you want to have IBM layout swap the key caps on the keyboard and exchange the following codeline:

    // modifiers: Shift left, Shift right, -, Win left, Crtl left, Ctrl right, Alt left, Alt right
      0x02, 0x20, 0x00, 0x08, 0x01, 0x10, 0x04, 0x40

best regards
Olaf

This would definitely make Amiga emulation (Amiga Forever and the like) systems more interesting - Glad I kept my 2000 and keyboard around...

Hi!

I've uploaded the script with joystick function but nothing happens when I press the buttons or move around with the joystick. The arduino seems to register every button and movement on the tx led.

Hi ,
did you put the HID gamepad descriptor in HID.c as described in Arduino Forum ?
Can you see the 2 joysticks in start/ system / gamecontroller ?

Hi,

Great work my A4000 keyboard is working on my Pegasos II !

However I have a couple of questions :

-Would it be a possible to get a PS/2 outpout on spare arduino's pins and how difficult would it be to modify the sketch to get this to work ?
-As the A4000 keyboard doesn't have the kbrst signal is it possible to make the arduino act as a reset switch hooked to the motherboard after reading the CTRL-A-A keypress sequence ?
-The CTRL-A-A seems to freeze the arduino so that I have to push the reset switch on the leonardo board to get it work again ...

As I said it befor it is an A4000 keyboard and this differs from A500 and A2000 keyboards since it hasn't the electrical reset line only clock and data line

Regards

Michel

I had some issues with putting the code in the HID.cpp

"1.0.3\hardware\arduino\cores\arduino\HID.cpp:420: error: expected unqualified-id before numeric constant"

But the other funny thing is that the Tac-2's wiring is

Front
Back
Left
Right
GND
Button

So I can't find any 5v wire, so I wired up the cables with your diagram and as I mentioned before it registers on TX led that something is moving of being pressed on the joystick.

Would it be possible if you uploaded a HID.cpp file that is configured or the code of the HID.cpp.
And thanks for all your hard work:)

@MikePig:
-Would it be a possible to get a PS/2 outpout on spare arduino's pins and how difficult would it be to modify the sketch to get this to work ?
I guess this might be possible.
please visit kbdbabel.org . there you'll find an amiga to ps2 converter with the related sourcecode. maybe you can use this as a template.

-As the A4000 keyboard doesn't have the kbrst signal is it possible to make the arduino act as a reset switch hooked to the motherboard after reading the CTRL-A-A keypress sequence ?
This could work if the amiga keyboard controller transmits the CTRL-A-A sequence on the dataline.
The motherboard RESET input normally needs a GND signal. So one have to try if the arduino output switched to LOW will be enough. Otherwise you'll need an additional transistor, like a FET, that switches to GND.

-The CTRL-A-A seems to freeze the arduino so that I have to push the reset switch on the leonardo board to get it work again ...
I haven't noticed this with the A500 keyboard. maybe it helps to add a case for CTRL-A-A in the sketch

@Farb:
+5V is only needed if the joystick contains circuits like autofire,...

attached is my hid.cpp...

HID.cpp (16.4 KB)

@all:
the code is made for a german keyboard layout, for other layouts the keytable and parts of the code have to be modified.

Thank you! It all works now. But I had to configure some stuff:)

update:
"{","[" had no function - fixed

Hi!

I'm building a PC-in-a-A1200-case, and are attempting to get this code to work with a A500 kbd (which fits perfectly in a A1200 case btw). Initially I bought a Keyrah to use as a KBD adapter, but it turned out to be a C64/128 specific one so I figured I might be able to do it with an Arduino instead. Fortunately I found this sketch so I won't have to do it all from scratch :slight_smile:

However, I keep getting a repeated key press of the ">"-key when I plug in the keyboard. I get no other response. The power led is lit up and the caps lock key works for 10 seconds or so (i.e the little led lights up in the key), but then it stops responding. Maybe there is some issue with the initial handshake?

I'm fairly new to Arduino and hardware hacking in general, so right now I'm at the stage where I'm not really sure where to start troubleshooting. Any pointers would be very helpful!

BTW, I'm using the Arduino Micro, but AFAIK it's the same chip as the Leonardo, but on a smaller PCB, so the same sketch should work right?

Never mind. Got it working! Typing this on my A500 KBD :slight_smile:

Turns out the the pin mapping was wrong. Data should be 8 and clock should be 9. Olaf, you might want to change this in your original post!

Anyways, thanks for the sketch!

@Splashdust, You're right. Data and Clock were swapped. I changed it in the original post. Thank you.

Everything is OK with PC/Windows and OSX but i have mist (Atari and Amiga FPGA clone). It seems like Arduino is not recognized as HID keyboard. I see blinking TX LED so keycodes are send to mist but no reaction in mist menu nor amiga software.

Well, the next part of the project would be: A computer keyboard to amiga A500 / 1000 / 2000 / 4000 xd. Some people like me prefers to use a real Amiga, but a working keyboard is my problem right now. So why not build a ps2 PC to ps2 amiga convertor. Ok, you can buy it for only 30 euro but that's the too easy way and i want it "now" xd.
And once the code is written and tested everyone could built one, cheaper then the ones you can buy.

Thanks everyone I have been able successfully to build this and is big step towards finishing my awesome Amiga emulator project! But I found that the code did not work perfectly with US Qwerty keyboard map, so I have fixed that, and I have also added code for PrtScrn, which was not there.

#define BITMASK_A500CLK 0b00010000    // IO 8
#define BITMASK_A500SP  0b00100000    // IO 9
#define BITMASK_A500RES 0b01000000    // IO 10
#define BITMASK_JOY1    0b10011111    // IO 0..4,6
#define BITMASK_JOY2    0b11110011    // IO A0..A5    
#define SYNCH_HI        0
#define SYNCH_LO        1
#define HANDSHAKE       2
#define READ            3
#define WAIT_LO         4 
#define WAIT_RES        5

KeyReport _keyReport;
uint32_t counter = 0;
uint8_t Joy, MemoJoy1, MemoJoy2, state, bitn, key, fn,keydown, ktab[0x68]={
  // Tilde, 1-9, 0, sz, Accent, backslash, Num 0 (00 - 0F)
  0x35, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x2D, 0x2E, 0x31,    0, 0x62,
  // Q bis +, -, Num 1, Num 2, Num3 (10 - 1F)
  0x14, 0x1A, 0x08, 0x15, 0x17, 0x1C, 0x18, 0x0C, 0x12, 0x13, 0x2F, 0x30, 0   , 0x59, 0x5A, 0x5B,
  // A-#, -, Num 4, Num 5, Num 6 (20 - 2F)
  0x04, 0x16, 0x07, 0x09, 0x0A, 0x0B, 0x0D, 0x0E, 0x0F, 0x33, 0x34, 0x32, 0,    0x5C, 0x5D, 0x5E,
  // <>,Y- -, -, Num . , Num 7, Num 8, Num 9 (30 - 3F)
  0x64, 0x1D, 0x1B, 0x06, 0x19, 0x05, 0x11, 0x10, 0x36, 0x37, 0x38,    0, 0x63, 0x5F, 0x60, 0x61,
  // Space, BS, Tab, Enter, Return, ESC, Del, -, -, -, Num -, -, up, down, right, left (40 - 4F)
  0x2C, 0x2A, 0x2B, 0x58, 0x28, 0x29, 0x4C,    0,    0,    0, 0x56,    0, 0x52, 0x51, 0x4F, 0x50,
  // F1-F10, -, -, Num /, Num *, Num +, - (50 - 5F)
  0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43,    0,    0, 0x54, 0x55, 0x57,    0,
  // modifiers: Shift left, Shift right, -, Crtl left, Alt left, Alt right, Win (amiga) left, Ctrl (amiga)right
  0x02, 0x20, 0x00, 0x01, 0x04, 0x40, 0x08, 0x10
};

void setup() {
  // Joystick 1 (Port D)
  DDRD = ~BITMASK_JOY1; // direction INPUT
  PORTD = BITMASK_JOY1; // activate PULLUP
  
  // Joystick 2 (Port F)
  DDRF = ~BITMASK_JOY2; // direction INPUT
  PORTF = BITMASK_JOY2; // activate PULLUP

  // Keyboard (Port B)
  DDRB = ~(BITMASK_A500CLK | BITMASK_A500SP | BITMASK_A500RES);  // direction INPUT
}


void loop() {
  // Joystick 1
  Joy = ~PIND & BITMASK_JOY1;
  if (Joy != MemoJoy1) {
    HID_SendReport(3, &Joy, 1);
    MemoJoy1 = Joy;
  }  

 // Joystick 2
  Joy = ~PINF & BITMASK_JOY2;
  if (Joy != MemoJoy2) {
    HID_SendReport(4, &Joy, 1);
    MemoJoy2 = Joy;
  }  
  
  // Keyboard
    if (((PINB & BITMASK_A500RES)==0) && state!=WAIT_RES) {   // Reset
    interrupts();
    keystroke(0x4C,05);        // CTRL+ALT+DEL
    fn=0;
    state=WAIT_RES;
  }
  
  else if (state==WAIT_RES) {   // Waiting for reset end
    if ((PINB & BITMASK_A500RES)!=0) state=SYNCH_HI;
  }
  
  else if (state==SYNCH_HI) {   // Sync-Pulse HI
    if ((PINB & BITMASK_A500CLK)==0) state=SYNCH_LO;
  }

  else if (state==SYNCH_LO) {   // Sync-Pulse LOW
    if ((PINB & BITMASK_A500CLK)!=0) state=HANDSHAKE;
  }
 
  else if (state==HANDSHAKE) {  // Handshake
    if (counter==0) {
      DDRB |= BITMASK_A500SP;   // set IO direction to OUTPUT
      PORTB &= ~BITMASK_A500SP; // set OUTPUT to LOW
      counter=millis();
    }
    else if (millis()-counter>10) {
      counter=0;
      DDRB &= ~BITMASK_A500SP;   // set IO direction to INPUT
      state=WAIT_LO;
      key=0;
      bitn=7;
    }
  }
  
  else if (state==READ) {        // read key message (8 bits)
    if ((PINB & BITMASK_A500CLK)!=0) {  
      if (bitn--){
        key+=((PINB & BITMASK_A500SP)==0)<<(bitn); // key code (add bits 0...6)
        
        state=WAIT_LO;
      }
      else {  // read last bit (key down)    
        keydown=((PINB & BITMASK_A500SP)!=0); // true if key down
        interrupts();
        state=HANDSHAKE;
        if (key==0x5F)  fn=keydown;  // "Help" key: special function on/off
        else if (key==0x62) keystroke(0x39,0x00);  // CapsLock
        else {
          if (keydown){
            // keydown message received------
            if (fn) {
              // special function with "Help" key 
              if (key==0x50) keystroke(0x44,0);  // F11
              else if (key==0x51) keystroke(0x45,0);  // F12
              else if (key==0x5A) keystroke(0x53,0);  // NumLock
              else if (key==0x5B) keystroke(0x47,0);  // ScrollLock
              else if (key==0x5D) keystroke(0x46,0);  // PrtSc
            }
            else {
              if (key==0x5A) keystroke(0x26,0x20); // (
              else if (key==0x5B) keystroke(0x27,0x20); // )
              else if (key < 0x68) keypress(key);  // Code table
            }
          }
          else {
            // keyrelease message received
            if (key < 0x68) keyrelease(key);  // Code table
          }
        }
      }
    }
  }
  
  else if (state==WAIT_LO) {   // waiting for the next bit
    if ((PINB & BITMASK_A500CLK)==0) {
      noInterrupts();
      state=READ;
    }
  }
}
    

void keypress(uint8_t k) {
  
  if (k > 0x5f) _keyReport.modifiers |= ktab[key];  // modifier
  else {  
    for (uint8_t i=0; i<6; i++) {
      if (_keyReport.keys[i] == 0) {
         _keyReport.keys[i] = ktab[key];
         break;
      }
    }
  }
  HID_SendReport(2,&_keyReport,8);
}


void keyrelease(uint8_t k) {

  if (k > 0x5f) _keyReport.modifiers &= ~ktab[key];  // modifier
  else {  
    for (uint8_t i=0; i<6; i++) {
      if (_keyReport.keys[i] == ktab[key]) _keyReport.keys[i] = 0;
    }
  }
  HID_SendReport(2,&_keyReport,8);
}


void keystroke(uint8_t k, uint8_t m) {
  
  unsigned short memomodifiers = _keyReport.modifiers; // save last modifier state
    for (uint8_t i=0; i<6; i++) {
      if (_keyReport.keys[i] == 0) {
         _keyReport.keys[i] = k;
         _keyReport.modifiers = m;
         HID_SendReport(2,&_keyReport,8);
         _keyReport.keys[i] = 0;
         _keyReport.modifiers = memomodifiers; // recover modifier state
         HID_SendReport(2,&_keyReport,8);
         break;
      }
    }
}

If you are hacking this code or testing your keyboard you may find these resources useful;
Keyboard Tester - http://www.keyboardtester.com/
Keyboard Scancode reader - Keyboard Codes Display
Keyboard scancodes explained - Scan Codes Demystified

Thank you Steve,
I added PrtSc in my original Sketch and made a hint to your QWERTY Layout in the first post.

Sorry to revive a thread from the dead, but I just picked up an Amiga 2000 and my first ever Arduino. I am a keyboard enthusiast which is what led me to the Amiga 2000, with the intention that I'd be able to use it based off the information I found in this thread and a Leonardo that I purchased.

Basically, I'm a script kiddie.

I'm running into an issue, when I "Verify" the Copy Pasta I did from Steve_Reaver I get back an error that 'KeyReport' does not name a type. Here's the log:

Amiga_2000_QWERTY_Copy_Pasta:13: error: 'KeyReport' does not name a type
Amiga_2000_QWERTY_Copy_Pasta.ino: In function 'void setup()':
Amiga_2000_QWERTY_Copy_Pasta:38: error: 'DDRF' was not declared in this scope
Amiga_2000_QWERTY_Copy_Pasta:39: error: 'PORTF' was not declared in this scope
Amiga_2000_QWERTY_Copy_Pasta.ino: In function 'void loop()':
Amiga_2000_QWERTY_Copy_Pasta:50: error: 'HID_SendReport' was not declared in this scope
Amiga_2000_QWERTY_Copy_Pasta:55: error: 'PINF' was not declared in this scope
Amiga_2000_QWERTY_Copy_Pasta:57: error: 'HID_SendReport' was not declared in this scope
Amiga_2000_QWERTY_Copy_Pasta.ino: In function 'void keypress(uint8_t)':
Amiga_2000_QWERTY_Copy_Pasta:146: error: '_keyReport' was not declared in this scope
Amiga_2000_QWERTY_Copy_Pasta:149: error: '_keyReport' was not declared in this scope
Amiga_2000_QWERTY_Copy_Pasta:155: error: '_keyReport' was not declared in this scope
Amiga_2000_QWERTY_Copy_Pasta:155: error: 'HID_SendReport' was not declared in this scope
Amiga_2000_QWERTY_Copy_Pasta.ino: In function 'void keyrelease(uint8_t)':
Amiga_2000_QWERTY_Copy_Pasta:161: error: '_keyReport' was not declared in this scope
Amiga_2000_QWERTY_Copy_Pasta:164: error: '_keyReport' was not declared in this scope
Amiga_2000_QWERTY_Copy_Pasta:167: error: '_keyReport' was not declared in this scope
Amiga_2000_QWERTY_Copy_Pasta:167: error: 'HID_SendReport' was not declared in this scope
Amiga_2000_QWERTY_Copy_Pasta.ino: In function 'void keystroke(uint8_t, uint8_t)':
Amiga_2000_QWERTY_Copy_Pasta:173: error: '_keyReport' was not declared in this scope
Amiga_2000_QWERTY_Copy_Pasta:178: error: 'HID_SendReport' was not declared in this scope

I gotta assume Steve's code is good and since all I did was copy and paste, I gotta assume it's something wrong on my side.

Any input?

So it looks like I need to include a library of some sort, and I've tried all the libraries that the Arduino 1.0.5 IDE comes with but none of them worked.

Can anyone help?