Attached is my version of the sketch for use with an Amiga Emulator on Raspberry Pi, "Amibian". The RasPi fits very easily into an A500 case with the motherboard/floppy removed, so I wanted to use the stock A500 keyboard.
I loaded this sketch into the Leonardo with the web editor, and it works. For testing, I actually used an Amiga 2000 keyboard with only 4 pins. It is missing the Reset pin, so I had to comment out the CTRL ALT DEL code otherwise I get a constant signal of soft reset from the Leonardo. I don't really need this function for the emulator anyway. It was trial-and-error trying to find the pinout for the A2000 keyboard. This might save someone time:
KBD=ARD
Pin1=GND
Pin2=5v
Pin3=Pin8
Pin4=Pin9
I set my help key and numpad up for use with the emulator. I didn't need all the extra navigation stuff, so I mapped the "Help" key to be F12 for easy access to the emulator GUI, and I set the NumL and ScrL as the primary function for those keys. Also added a LED on pin 5 to light when NumL is active (not sure if I will wind up using it, but someone may).
I found a chart with Amiga keycodes here: http://wiki.amigaos.net/wiki/Keymap_Library
Scroll down to the "Raw Key Table", and look at the 3rd Column "USB Code". Substitute the first two digits with a 0x (Ex: 0034 needs to be 0x34 in your code).
Thanks to the OP, et. all.
#include <Keyboard.h> // FOR NEWEST IDE 1.6.9
#define HID_SendReport(id,data,len) HID().SendReport(id,data,len) // IDE 1.6.9
#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, 0xE3, 0xE7
};
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
//numlock LED
pinMode(5, OUTPUT);
}
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(); //this doesn't work with 4 pin A2000 keyboards
// 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
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==0x62) keystroke(0x39,0x00); // CapsLock
else {
if (keydown){
// keydown message received------
if (key==0x5A) {
keystroke(0x53,0); // Num lock active without modifier
if (digitalRead(5)) // Num lock LED on Pin
digitalWrite(5, LOW);
else
digitalWrite(5, HIGH);
}
else if (key==0x5B) keystroke(0x47,0); // Scroll lock active without modifier
else if (key==0x5F) keystroke(0x45,0); // Help is F12 to bring up UAE emulator interface
else if (key < 0x68) keypress(key); // All remaining keys via 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;
}
}
}