Amiga 500 Tastatur am Arduino RightMenu Taste? Brauche Hilfe

Hallo
Ich arbeite seit einiger Zeit an dem hier schon vor langem geposteten Projekt,
daß eine Amiga Tastatur an einem Arduino Leonardo in eine HID Tastatur ermöglicht.
Leider ist das Projekt von 2012 und niemand antwortet mehr darauf.
Aus diesem Grund probiere ich es halt mal im deutschen Forum :slight_smile:

So…jetzt gehts los…

Der Sketch funktioniert soweit ganz gut.
Ein Problem habe ich jedoch damit:

Es geht um diese Zeile:
0x80, //RECHTS-AMIGA

Ich benötige dringend den Hex Code für die Rechte Win-Menü Taste.
Ich benötige diese Taste damit ich auf einem Pi Amiga Emulator den typischen Amiga Affengriff Reset durchführen kann.
Dieser geht nur mit CTRL+LeftWin+RightMenu

Ich konnte nur den HEX Code der RightWin Taste finden und zuweisen, jedoch geht das nicht mit dem Uae4arm Reset.

Irgendwie kann ich diese nicht in den passenden HEX Keycode finden.
Ich habe schon Vorschläge erhalten wie Right MENU key - VK_RMENU: 0xA5 usw.,
jedoch gehen diese nicht.

Kann es sein das die Keyboard Library nicht vollständig ist?

Ich benutze folgendes an Soft und Hardware:
Arduino Leonardo
Keyboard Library 1.0.1
HID Library 1.0.0
Arduino Software 1.8.1

Wäre toll wenn jemand das lösen könnte.
Ich habe leider nicht soviel Erfahrung auf diesem Gebiet, :slight_smile:

Gruß Markus

Hier habt ihr mal den Sketch:

#include <Keyboard.h>

#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,

0x02, //SHIFT-LINKS
0x20, //SHIFT-RECHTS
0x00, 
0x01, //LINKS-CTRL
0x04, //RECHTS-ALT
0x40, //LINKS-AMIGA
0x08, //LINKS-ALT

0x80, //RECHTS-AMIGA

//0xA5, //Test
//0xe7, //Test
//0x9F, //Test
};

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;
     }
   }
}

Ok...anscheinend hat niemand eine Lösung....

Ich blicke bei dem Sketch leider nicht durch, aber der Leonardo erzeugt mit

Keyboard.press(KEY_RIGHT_GUI);

den Code für die rechte Windows-Taste.
Vielleicht hilft dir das weiter.

Gutes Gelingen!

Bei dem Sketch geht es darum, das Binärdaten der Amiga Tastatur interpretiert
werden in ein HID konformes Format.
Die Amiga500 Tastatur übergibt die Daten seriell im Binärformat.

Das funktioniert soweit mit allen Tasten ganz gut.

Auch geht die linke Windows Taste und die rechte Windows Taste.

Ich benötige jedoch den Hex Code für die rechte Windowsmenü Taste.

Nicht zu verwechseln mit der rechten Windows Taste. Die gab es mal bei älteren Tastaturen.
Standard ist ja jetzt auf der rechten Seite die Menütaste.

Das hier:

 // 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,

sind die passenden Hex Codes die im HID Interface erkannt werden und dann ausgegeben werden.

CypherXG:
Ich benötige jedoch den Hex Code für die rechte Windowsmenü Taste.

Nicht zu verwechseln mit der rechten Windows Taste. Die gab es mal bei älteren Tastaturen.
Standard ist ja jetzt auf der rechten Seite die Menütaste.

Ja, das hab ich verwechselt.

Hab das jetzt mal mit meinem Leonardo durchgespielt und mit
0x65
lässt sich diese "Windowsmenü-Taste" ansprechen (OS: Win 7).

Ich habe zum Testen allerdings die Werte in der HID.cpp modifiziert.

Kannst du das mal posten. Dann verändere ich das bei mir auch.
Wäre super... :slight_smile:

CypherXG:
Kannst du das mal posten. Dann verändere ich das bei mir auch.

Das mache ich gerne, ich muss allerdings sagen, dass es ein "ziemlicher Hack" ist, aber bei mir funktioniert es zufriedenstellend. :slight_smile:
Das bedeutet: es gibt sicher auch eine "sauberere" Lösung, aber damit mögen sich berufenere Leute beschäftigen :slight_smile:

Die "rechte Windows-Menü-Taste" ist eine ganz normale Taste, allerdings ist sie beim Leonardo "nicht vorgesehen". Das lässt sich aber ändern.
Die Keyboard-Funktionalität des Leonardo wird durch die Datei "HID.cpp" bestimmt.
Die Datei ist bei mir hier zu finden (Win 7, Arduino IDE 1.6.5-r5, ZIP-Version): ...arduino-1.6.5-r5\hardware\arduino\avr\cores\arduino\HID.cpp
(Bei späteren Versionen der IDE funktioniert das anscheinend anders - wie das muss ich erst herausfinden. Edit: Schon herausgefunden - siehe ganz unten)

Wenn man HID.cpp mit einem Texteditor öffnet, dann findet man bei etwa der Mitte der Datei folgendes:

const uint8_t _asciimap[128] =
{
 0x00,             // NUL
 0x00,             // SOH
 0x00,             // STX
 0x00,             // ETX
 0x00,             // EOT
 0x00,             // ENQ
 0x00,             // ACK  
 0x00,             // BEL
 0x2a, // BS Backspace
 0x2b, // TAB Tab
 0x28, // LF Enter
 0x00,             // VT 
 0x00,             // FF 
 0x00,             // CR 
...

Wie der Name des Arrays schon andeutet (asciimap) sind hier wohl die ASCII-Zeichen den Keyboardtasten zugeordnet. Weiter unten in dem Array (nicht mehr in diesem Codeschnipsel zu sehen) sind die "ganz normalen" Zeichen zu finden, also 0 bis 9, A bis Z und so weiter. Das interessiert uns im Moment aber nicht, denn wir wollen ja eine zusätzliche Tastenfunktion "hineinhacken".

Man kann erkennen, dass die ersten Einträge des Arrays mit 0x00 versehen sind. Den ASCII-Zeichen 0 bis 7 sind keine Tasten zugeordnet - das macht auch Sinn, diese Zeichen sind ja keine "druckbaren" Zeichen. 8, 9 und 10 sind aber sehr wohl Tasten zugeordnet - auch das ist logisch, denn das sind die Tasten Backspace, TAB, ENTER.

Die "rechte Windows-Menü-Taste" hat Code 0x65 und den schummeln wir jetzt zu einem der ersten Einträge im Array dazu zum Beispiel bei Index 2. Der Anfang des Array sieht dann so aus:

const uint8_t _asciimap[128] =
{
 0x00,             // NUL   Index 0
 0x00,             // SOH  Index 1
 0x65,             // Windows-Menu  Index 2

Jetzt brauchen wir noch ein Konstrukt um die Taste mit ASCII-Code 2 anzusprechen.
Beispiel:

#define KEY_WIN_MENU  2

void setup() {
  Keyboard.begin();
  delay(7000);  // Zeit, um zum Texteditor zu wechseln
  
  Keyboard.write('a');
  Keyboard.write('b');
  Keyboard.write('c');
  Keyboard.write(KEY_WIN_MENU);
}
 
void loop() {
}

Die "rechte Windows-Menü-Taste" ist in der Arduino-IDE anscheinend ohne Funktion (zumindest bei mir) aber in den meisten Anderen Programmen (z.B. im Texeditor) funktioniert sie.
Wenn du jetzt den Leonardo ansteckst und im Texteditor bist, dann erscheinen die Zeichen "a b c" und danach wird die "rechte Windows-Menü-Taste" betätigt.

Edit:
Bei IDE 1.8.2 ist das Array "asciimap" wo anders zu finden, nämlich hier:
...arduino-1.8.2\libraries\Keyboard\src\Keyboard.cpp
Bei welcher IDE-Version die Umstellung stattfand wäre noch herauszufinden.

Jupp. So sieht es aus.
Dort musste ich alles eintragen, jedoch leider funktioniert es nicht.
Ich kann über die Amiga Tastatur nicht die RMenü Taste abrufen, warum auch immer.
Ich muss mir da wohl was anderes einfallen lassen.