Go Down

Topic: AMIGA 500/1000/2000 Keyboard Interface (Read 23453 times) previous topic - next topic

olivier78860

#30
Jan 05, 2016, 03:51 pm Last Edit: Jan 05, 2016, 04:11 pm by olivier78860
Hi all,

This is 2016 and some things had to be done to adapt the source code Olaf wrote to the 1.6.9 IDE with the Arduino Leonardo Rev 4.0.
Forgive me if it sounds absolutely obvious to everyone else, but I prefer to link to the question I asked, in case it is helpful to anyone, as noob as I am !

http://forum.arduino.cc/index.php?topic=369773.0

Code: [Select]

#include <Keyboard.h> // FOR NEWEST IDE 1.6.9

#define BITMASK_A500CLK 0b00010000    // IO 8
#define BITMASK_A500SP  0b00100000    // IO 9
#define BITMASK_A500RES 0b01000000    // IO 10
#define SYNCH_HI        0
#define SYNCH_LO        1
#define HANDSHAKE       2
#define READ            3
#define WAIT_LO         4
#define WAIT_RES        5
#define HID_SendReport(id,data,len) HID().SendReport(id,data,len) // IDE 1.6.9
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, -, Win left, Crtl left, Ctrl right, Alt left, Alt right
  0x02, 0x20, 0x00, 0x08, 0x01, 0x10, 0x04, 0x40
};

void setup() {
 // Keyboard (Port B)
  DDRD = ~(BITMASK_A500CLK | BITMASK_A500SP | BITMASK_A500RES);  // direction INPUT
}

void loop() {
 
  // 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==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); // |,\
              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;
      }
    }
}



On a side note, I had to swap pins 8 & 9 for it to work. It seems it is Amiga-keyboard dependent. If it doesn't work with the proposed setup, just swap the cables connected to these pins.

And my deepest thanks to the nice people who wrote that code and to the person who gave me the issue's solution :)

Of course, this is typed with my A500 keyboard :D

chking

I'm working on this same project and found I also had to swap pins 8 and 9.  Once I do that though the keyboard outputs a stream of ~ characters.  I took apart the keyboard to clean it and I'm concerned that I might have ruined it or not put it back together correctly.  Anyone else run into problems like this?

olivier78860

I had exactly the same issue.

I uploaded the empty program to the Arduino, then unplugged it, and then reuploaded the program to the Arduino.

Also, check your connections and change the USB cable. I had two, one generic and one from my Samsung smartphone. Only the Samsung one gave good results.

olaf

#33
Jan 06, 2016, 02:54 pm Last Edit: Jan 06, 2016, 03:00 pm by olaf
Dear Olivier,

Please apologize my delayed answer. I read your mail today and saw that you have fixed the problem allready.
Many thanks for publishing the solution in this thread!

Yes , it`s a long time ago I made this code, but it still works surprisingly well ;-).
I use the keyboard on my retro amiga notebook conversion every day. I`m actually writing this post on the Amiga Keyboard. Attached are some pictures of my Amiga 500 conversion.

I hope your amiga project  works as well and my code is usefull for you and all other members.

yours sincerely
Olaf
Dipl. Ing. (FH) Olaf Berthold
Hardware- und Softwareentwicklung

chking

Olaf, in your pictures, what are the two big green components connected to 5 volts and ground?

olivier78860

Those are condensators. I suspect it's to make sure the disk and power led get the constant 5V they need, as I have read somewhere that the Arduino couldn't provide with constant current.

If the specs of these condensators could be given, that would be nice !

And thanks Olaf for the code again :)

RetroMachine

#36
Jan 23, 2016, 07:42 am Last Edit: Jan 23, 2016, 01:50 pm by RetroMachine
I have this working and have wired up an A500 keyboard :)

Thanks Olaf and olivier78860

kolla

Hello, I have a slightly similar potential project I am pondering on :) Instead of USB hid, I want old school PS/2, so I can use real Amiga keyboard and mouse on my Minimig. That is a nice little project in itself, but it would be even more awesome if I manage to have one arduino connected to the PS/2 ports on the Minimig and another arduino to the Amiga keyboard and mouse, the two arduinos communicating wirelessly. And then think further, what if there are multiple systems (my Minimig (PS/2), my MIST (USB hid)and my CD32 (Amiga mini-DIN)) and I want to control them all from one remote unit, which acts like a wireless keyboard+mouse+joysticks switch... one can dream :)

builder_guy


olivier78860

And my project, finally completed yesterday.
http://imgur.com/gallery/GvEMv

polymorph

Olaf, in your pictures, what are the two big green components connected to 5 volts and ground?
They do NOT look like capacitors, they look like large multi-watt resistors. But the images are too small to tell.

Olaf?
Steve Greenfield AE7HD
Drawing Schematics: tinyurl.com/23mo9pf - tinyurl.com/o97ysyx - tinyurl.com/q7uqnvn
Multitasking: forum.arduino.cc/index.php?topic=223286.0
gammon.com.au/blink - gammon.com.au/serial - gammon.com.au/interrupts

DJulius

Hi, i got amiga 500 with a azerty keyboard, i would like to modify the code but i don't know how to do that, can you help me ?

olivier78860

#42
Apr 27, 2016, 10:04 pm Last Edit: Apr 27, 2016, 10:11 pm by olivier78860
Djulius,
You can use the code as it is.
When installing Linux, just set your keyboard to French and the keys will be correctly assigned (there are imperfections due to the differences between back-in-the-day Amiga azerty and nowaday's PC azerty, though, especially on the number keys above the letters' alternates).
That's what I did and it works just fine.

Silver Dream

Hi all,

This is 2016 and some things had to be done to adapt the source code Olaf wrote to the 1.6.9 IDE with the Arduino Leonardo Rev 4.0.
Forgive me if it sounds absolutely obvious to everyone else, but I prefer to link to the question I asked, in case it is helpful to anyone, as noob as I am !
Thank you for posting this. It saved me some time for sure. Summing up the changes - in order to compile the sketch cleanly within the Arduino 1.6.9, the following changes need to be made:
  • Keyboard.h needs to be included in order to get the type for KeyReport
  • HID_SendReport have to be replaced with HID().SendReport (I prefer this, rather than working the issue around with #define)
  • parentheses need to be added around DDRD and DDRF assignments in order to avoid warnings

Code: [Select]

#include <Keyboard.h> // FOR NEWEST IDE 1.6.9

[...]

  DDRD = ~(BITMASK_JOY1); // direction INPUT
  DDRF = ~(BITMASK_JOY2); // direction INPUT

szczuru

Can it be combines with dual Amiga Joysticks (on Arduino Nano)? From here:
http://forum.arduino.cc/index.php?topic=134108.0

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy